[WIP] Working 2fa email auth

This commit is contained in:
slawkens 2025-06-22 18:50:54 +02:00
parent 96d6e04bd2
commit b3dfc56c96
17 changed files with 513 additions and 195 deletions

View File

@ -20,61 +20,102 @@ csrfProtect();
/** /**
* @var OTS_Account $account_logged * @var OTS_Account $account_logged
*/ */
$step = isset($_REQUEST['step']) ?? ''; $step = $_REQUEST['step'] ?? '';
$code = $_REQUEST['email-code'] ?? '';
if ((!setting('core.mail_enabled')) && ACTION == 'email-code') { if ((!setting('core.mail_enabled')) && ACTION == 'email-code') {
$twig->display('error_box.html.twig', ['errors' => ['Account two-factor e-mail authentication disabled.']]); $twig->display('error_box.html.twig', ['errors' => ['Account two-factor e-mail authentication disabled.']]);
return; return;
} }
$twoFactorAuth = new TwoFactorAuth($account_logged); if (!isset($account_logged) || !$account_logged->isLoaded()) {
$current_session = getSession('account');
if($current_session) {
$account_logged->load($current_session);
}
}
$twoFactorAuth = TwoFactorAuth::getInstance($account_logged);
if (ACTION == 'email-code') { if (ACTION == 'email-code') {
if ($step === 'verify') { if ($step == 'resend') {
$code = $_POST['email-code'] ?? ''; if ($twoFactorAuth->hasRecentEmailCode(15 * 60)) {
$errors = ['Sorry, one email per 15 minutes'];
}
else {
$twoFactorAuth->resendEmailCode();
}
if (!empty($errors)) {
$twig->display('error_box.html.twig', ['errors' => $errors]);
}
$twig->display('account.2fa.email-code.login.html.twig');
}
else if ($step == 'activate') {
if (!$twoFactorAuth->hasRecentEmailCode(15 * 60)) {
$twoFactorAuth->resendEmailCode();
}
if (isset($_POST['save'])) {
if (!empty($code)) {
$twoFactorAuth->setAuthGateway(TwoFactorAuth::TYPE_EMAIL);
if ($twoFactorAuth->getAuthGateway()->verifyCode($code)) { if ($twoFactorAuth->getAuthGateway()->verifyCode($code)) {
$twoFactorAuth->getAuthGateway()->deleteOldCodes(); $serverName = configLua('serverName');
//session(['2fa_skip' => true]); $twoFactorAuth->enable(TwoFactorAuth::TYPE_EMAIL);
header('Location: account/manage'); $twoFactorAuth->deleteOldCodes();
exit;
}
}
else if ($step == 'resend') {
$twoFactorAuth->getAuthGateway()->resendEmailCode();
$twig->display('account.2fa.email_code.html.twig'); $twig->display('success.html.twig', [
} 'title' => 'Email Code Authentication Activated',
else if ($step == 'confirm-activate') { 'description' => sprintf('You have successfully activated <b>email code authentication</b> for your account. This means an <b>email code</b> will be sent to the email address assigned to your account whenever you try to log in to the %s client or the %s website. In order to log in, you will need to enter the <b>most recent email code</b> you have received.', $serverName, $serverName)
$account2faCode = $account_logged->getCustomField('2fa_email_code'); ]);
$account2faCodeTimeout = $account_logged->getCustomField('2fa_email_code_timeout');
if (!empty($account2faCodeTimeout) && time() - (int)$account2faCodeTimeout < (24 * 60 * 60)) { return;
$postCode = $_POST['email-code'] ?? '';
if (!empty($account2faCode)) {
if (!empty($postCode)) {
if ($postCode == $account2faCode) {
$twig->display('account.2fa.email-code.success.html.twig');
}
} }
else { else {
$errors[] = 'Invalid email code!';
}
}
else {
$errors[] = 'Your account dont have 2fa E-Mail code sent.';
}
}
else {
$errors[] = 'E-Mail Code expired.';
} }
} }
} }
if (!empty($errors)) { if (!empty($errors)) {
$twig->display('error_box.html.twig', ['errors' => $errors]); $twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [ }
'new_line' => true
]); $twig->display('account.2fa.email_code.html.twig', ['wrongCode' => count($errors) > 0]);
}
else if ($step == 'deactivate') {
if (!$twoFactorAuth->hasRecentEmailCode(15 * 60)) {
$twoFactorAuth->resendEmailCode();
}
if (isset($_POST['save'])) {
if (!empty($code)) {
if ($twoFactorAuth->getAuthGateway()->verifyCode($code)) {
$twoFactorAuth->disable();
$twoFactorAuth->deleteOldCodes();
$twig->display('success.html.twig',
[
'title' => 'Email Code Authentication Deactivated',
'description' => 'You have successfully <b>deactivated</b> the <b>Email Code Authentication</b> for your account.'
]
);
return;
}
else {
$errors[] = 'Invalid email code!';
}
}
}
if (!empty($errors)) {
$twig->display('error_box.html.twig', ['errors' => $errors]);
}
$twig->display('account.2fa.email-code.deactivate.html.twig', ['wrongCode' => count($errors) > 0]);
}
} }

View File

@ -58,8 +58,8 @@ if(!empty($login_account) && !empty($login_password))
setSession('remember_me', true); setSession('remember_me', true);
} }
$twoFactorAuth = new TwoFactorAuth($account_logged); $twoFactorAuth = TwoFactorAuth::getInstance($account_logged);
if (!$twoFactorAuth->process()) { if (!$twoFactorAuth->process($_POST['email-code'] ?? '')) {
return; return;
} }

View File

@ -8,6 +8,9 @@
* @copyright 2019 MyAAC * @copyright 2019 MyAAC
* @link https://my-aac.org * @link https://my-aac.org
*/ */
use MyAAC\TwoFactorAuth\TwoFactorAuth;
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account Management'; $title = 'Account Management';
@ -111,6 +114,8 @@ $twig->display('account.management.html.twig', array(
'account_registered' => $account_registered, 'account_registered' => $account_registered,
'account_rlname' => $account_rlname, 'account_rlname' => $account_rlname,
'account_location' => $account_location, 'account_location' => $account_location,
'twoFactorViews' => TwoFactorAuth::getInstance($account_logged)->getAccountManageViews(),
'actions' => $actions, 'actions' => $actions,
'players' => $account_players 'players' => $account_players,
)); ));

View File

@ -12,33 +12,5 @@ class EmailAuthGateway extends BaseAuthGateway implements AuthGatewayInterface
{ {
return AccountEMailCode::where('account_id', '=', $this->account->getId())->where('code', $code)->where('created_at', '>', time() - TwoFactorAuth::EMAIL_CODE_VALID_UNTIL)->first() !== null; return AccountEMailCode::where('account_id', '=', $this->account->getId())->where('code', $code)->where('created_at', '>', time() - TwoFactorAuth::EMAIL_CODE_VALID_UNTIL)->first() !== null;
} }
public function hasRecentEmailCode(): bool {
return AccountEMailCode::where('account_id', '=', $this->account->getId())->where('created_at', '>', time() - TwoFactorAuth::EMAIL_CODE_VALID_UNTIL)->first() !== null;
}
public function deleteOldCodes(): void {
AccountEMailCode::where('account_id', '=', $this->account->getId())->delete();
}
public function resendEmailCode(): void
{
global $twig;
$newCode = generateRandomString(6, true, false, true);
AccountEMailCode::create([
'account_id' => $this->account->getId(),
'code' => $newCode,
'created_at' => time(),
]);
$mailBody = $twig->render('mail.account.2fa.email-code.html.twig', [
'code' => $newCode,
]);
if (!_mail($this->account->getEMail(), configLua('serverName') . ' - Requested Authentication Email Code', $mailBody)) {
error('An error occurred while sending email. For Admin: More info can be found in system/logs/mailer-error.log');
}
}
} }

View File

@ -12,43 +12,126 @@ class TwoFactorAuth
const TYPE_NONE = 0; const TYPE_NONE = 0;
const TYPE_EMAIL = 1; const TYPE_EMAIL = 1;
const TYPE_APP = 2; const TYPE_APP = 2;
// maybe later
//const TYPE_SMS = 3;
const EMAIL_CODE_VALID_UNTIL = 24 * 60 * 60; const EMAIL_CODE_VALID_UNTIL = 24 * 60 * 60;
private static TwoFactorAuth $instance;
private \OTS_Account $account; private \OTS_Account $account;
private int $authType; private int $authType;
private EmailAuthGateway|AppAuthGateway $authGateway; private EmailAuthGateway|AppAuthGateway $authGateway;
public function __construct(\OTS_Account $account) { public function __construct(\OTS_Account|int $account) {
if (is_int($account)) {
$this->account = new \OTS_Account();
$this->account->load($account);
}
else {
$this->account = $account; $this->account = $account;
}
$this->authType = (int)$this->account->getCustomField('2fa_type'); $this->authType = (int)$this->account->getCustomField('2fa_type');
if ($this->authType === self::TYPE_EMAIL) { $this->setAuthGateway($this->authType);
$this->authGateway = new EmailAuthGateway($account);
}
else if ($this->authType === self::TYPE_APP) {
$this->authGateway = new AppAuthGateway($account);
}
} }
public function process() public static function getInstance($account = null): self
{
if (!isset(self::$instance)) {
self::$instance = new self($account);
}
return self::$instance;
}
public function process($code): bool
{ {
global $twig; global $twig;
if (!$this->isActive()) {
return true;
}
if (!empty($code)) {
if ($this->getAuthGateway()->verifyCode($code)) {
if ($this->authType === self::TYPE_EMAIL) {
$this->deleteOldCodes();
}
header('Location: account/manage');
return true;
}
else {
if (setting('core.mail_enabled')) {
$mailBody = $twig->render('mail.account.2fa.email-code.wrong-attempt.html.twig');
if (!_mail($this->account->getEMail(), configLua('serverName') . ' - Failed Two-Factor Authentication Attempt', $mailBody)) {
error('An error occurred while sending email. For Admin: More info can be found in system/logs/mailer-error.log');
}
}
define('HIDE_LOGIN_BOX', true);
$errors[] = 'Invalid email code!';
$twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.2fa.email-code.login.html.twig', ['wrongCode' => true]);
return false;
}
}
if ($this->authType == TwoFactorAuth::TYPE_EMAIL) { if ($this->authType == TwoFactorAuth::TYPE_EMAIL) {
if (!$this->authGateway->hasRecentEmailCode()) { if (!$this->hasRecentEmailCode(15 * 60)) {
$this->authGateway->resendEmailCode(); $this->resendEmailCode();
success('Resent email.'); //success('Resent email.');
} }
define('HIDE_LOGIN_BOX', true); define('HIDE_LOGIN_BOX', true);
$twig->display('account.2fa.email-code.login.html.twig'); $twig->display('account.2fa.email-code.login.html.twig');
return false; return false;
} }
return true; return true;
} }
public function setAuthGateway(int $authType): void
{
if ($authType === self::TYPE_EMAIL) {
$this->authGateway = new EmailAuthGateway($this->account);
}
else if ($authType === self::TYPE_APP) {
$this->authGateway = new AppAuthGateway($this->account);
}
}
public function getAccountManageViews(): array
{
$twoFactorView = 'account.2fa.protected.html.twig';
if ($this->authType == TwoFactorAuth::TYPE_EMAIL) {
$twoFactorView2 = 'account.2fa.email.activated.html.twig';
}
elseif ($this->authType == TwoFactorAuth::TYPE_APP) {
$twoFactorView2 = 'account.2fa.app.activated.html.twig';
}
else {
$twoFactorView = 'account.2fa.connect.html.twig';
$twoFactorView2 = 'account.2fa.email.activate.html.twig';
}
return [$twoFactorView, $twoFactorView2];
}
public function enable(int $type): void {
$this->account->setCustomField('2fa_type', $type);
}
public function disable(): void {
$this->account->setCustomField('2fa_type', self::TYPE_NONE);
}
public function isActive(): bool { public function isActive(): bool {
return $this->authType != self::TYPE_NONE; return $this->authType != self::TYPE_NONE;
} }
@ -60,4 +143,32 @@ class TwoFactorAuth
public function getAuthGateway(): AppAuthGateway|EmailAuthGateway { public function getAuthGateway(): AppAuthGateway|EmailAuthGateway {
return $this->authGateway; return $this->authGateway;
} }
public function hasRecentEmailCode($since = TwoFactorAuth::EMAIL_CODE_VALID_UNTIL): bool {
return AccountEMailCode::where('account_id', '=', $this->account->getId())->where('created_at', '>', time() - $since)->first() !== null;
}
public function deleteOldCodes(): void {
AccountEMailCode::where('account_id', '=', $this->account->getId())->delete();
}
public function resendEmailCode(): void
{
global $twig;
$newCode = generateRandomString(6, true, false, true);
AccountEMailCode::create([
'account_id' => $this->account->getId(),
'code' => $newCode,
'created_at' => time(),
]);
$mailBody = $twig->render('mail.account.2fa.email-code.html.twig', [
'code' => $newCode,
]);
if (!_mail($this->account->getEMail(), configLua('serverName') . ' - Requested Authentication Email Code', $mailBody)) {
error('An error occurred while sending email. For Admin: More info can be found in system/logs/mailer-error.log');
}
}
} }

View File

@ -0,0 +1,36 @@
<tr>
<td>
<div class="TableShadowContainerRightTop">
<div class="TableShadowRightTop" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rt.gif);"></div>
</div>
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);">
<div class="TableContentContainer">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody><tr>
<td class="LabelV"><b>Connect your {{ config.lua.serverName }} account to an authenticator app!</b>
<div style="float: right; font-size: 1px;">
<form action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="margin: 0px; padding: 0px;">
{{ csrf() }}
{% set button_name = 'Request' %}
{% include('buttons.base.html.twig') %}
</form>
</div>
</td>
</tr>
<tr>
<td>
<p>As a first step to connect an <b>authenticator app</b> to your account, click on "Request"! An email with a confirmation key will be sent to the email address assigned to your account.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="TableShadowContainer">
<div class="TableBottomShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bm.gif);">
<div class="TableBottomLeftShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bl.gif);"></div>
<div class="TableBottomRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-br.gif);"></div>
</div>
</div>
</td>
</tr>

View File

@ -0,0 +1,109 @@
{% set title = 'Deactivate Email Code Authentication' %}
{% set content %}
<table style="width:100%;">
<tbody>
<tr>
<td>
<div class="TableContentContainer ">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody>
<tr>
<td>To deactivate <b>two-factor email code authentication</b> for your account, enter the
received <b>email code</b> below. Note, however, that <b>email code authentication</b>
is an important security feature which helps to prevent any unauthorised access to your
Tibia account.
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td>
<div class="TableContentContainer">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody>
<tr>
<td>
<div style="float: right;">
<form
action="{{ getLink('account/2fa') }}?action=email-code&step=resend"
method="post"
style="padding:0;margin:0;"
>
{{ csrf() }}
{% set button_name = 'Resend Email Code' %}
{{ include('buttons.base.html.twig') }}
</form>
</div>
An <b>email code</b> has already been sent to the email address assigned to your
account.
Please check your email account's spam/junk filter and make sure that your mailbox is
not
full.<br>In case you need a new email code, you can request one by clicking on "Resend
Email
Code".
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td>
<div class="TableContentContainer">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody>
<tr>
<td>To complete the deactivation of <b>email code authentication</b>, please enter the <b>email
code</b> you received at the email address assigned to your account.
<div style="margin-top: 15px; margin-bottom: 15px;">
<div class="LabelV150 {{ wrongCode ? 'red' : '' }}" style="float:left;"><label
for="email-code">Email Code:</label></div>
<input form="form-code" id="email-code" name="email-code" maxlength="15"
autocomplete="off">
{% if wrongCode %}
<br/>
<div class="LabelV150" style="float:left;">&nbsp; </div>
<div class="FormFieldError">Invalid email code!</div>
{% endif %}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
{% endset %}
{% include 'tables.headline.html.twig' %}
<table style="width: 100%;">
<tbody>
<tr align="center" valign="top">
<td>
<form id="form-code" method="post" action="{{ getLink('account/2fa') }}?action=email-code">
{{ csrf() }}
<input type="hidden" name="step" value="deactivate">
<input type="hidden" name="save" value="1">
{% set button_name = 'Continue' %}
{% set button_color = 'green' %}
{{ include('buttons.submit.html.twig') }}
</form>
</td>
<td>
<form action="{{ getLink('account/manage') }}" method="post" style="padding:0;margin:0;">
{{ csrf() }}
{% set button_color = 'blue' %}
{{ include('buttons.back.html.twig') }}
</form>
</td>
</tr>
</tbody>
</table>

View File

@ -16,6 +16,7 @@
style="padding:0;margin:0;" style="padding:0;margin:0;"
> >
{{ csrf() }} {{ csrf() }}
{% set button_name = 'Resend Email Code' %} {% set button_name = 'Resend Email Code' %}
{{ include('buttons.base.html.twig') }} {{ include('buttons.base.html.twig') }}
</form> </form>
@ -40,11 +41,13 @@
<td><b>Email code authentication is activated for your account.</b><br><br>Please enter the <b>most <td><b>Email code authentication is activated for your account.</b><br><br>Please enter the <b>most
recent email code</b> you have received in order to log in.<br> recent email code</b> you have received in order to log in.<br>
<div style="margin-top: 15px; margin-bottom: 15px;"> <div style="margin-top: 15px; margin-bottom: 15px;">
<div class="LabelV150" style="float:left;">Email Code:</div> <div class="LabelV150 {{ wrongCode ? 'red' : '' }}" style="float:left;"><label for="email-code">Email Code:</label></div>
<form method="post" action="{{ getLink('account/2fa') }}?action=email-code&step=verify"> <input form="form-code" id="email-code" name="email-code" maxlength="15" autocomplete="off">
{{ csrf() }} {% if wrongCode %}
<input name="email-code" maxlength="15" autocomplete="off"> <br/>
</form> <div class="LabelV150" style="float:left;">&nbsp; </div>
<div class="FormFieldError">Invalid email code!</div>
{% endif %}
</div> </div>
</td> </td>
</tr> </tr>
@ -57,3 +60,26 @@
</table> </table>
{% endset %} {% endset %}
{% include 'tables.headline.html.twig' %} {% include 'tables.headline.html.twig' %}
<table style="width: 100%;">
<tbody>
<tr align="center" valign="top">
<td>
<form id="form-code" method="post" action="{{ getLink('account/manage') }}">
{{ csrf() }}
<input type="hidden" name="step" value="verify">
{% set button_name = 'Continue' %}
{% set button_color = 'green' %}
{{ include('buttons.submit.html.twig') }}
</form>
</td>
<td>
<form action="{{ getLink('account/manage') }}" method="post" style="padding:0;margin:0;">
{{ csrf() }}
{% set button_color = 'blue' %}
{{ include('buttons.back.html.twig') }}
</form>
</td>
</tr>
</tbody>
</table>

View File

@ -1,15 +0,0 @@
{% set title = 'Email Code Authentication Activated' %}
{% set content %}
<table style="width:100%;">
<tbody>
<tr>
<td>You have successfully activated <b>email code authentication</b> for your account. This means an <b>email
code</b> will be sent to the email address assigned to your account whenever you try to log in to the
{{ config.lua.serverName }} client or the {{ config.lua.serverName }} website. In order to log in, you will need to enter the <b>most recent email code</b> you have received.
</td>
</tr>
</tbody>
</table>
{% endset %}
{% include 'tables.headline.html.twig' %}
{{ include('account.back_button.html.twig') }}

View File

@ -0,0 +1,37 @@
<tr>
<td>
<div class="TableShadowContainerRightTop">
<div class="TableShadowRightTop" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rt.gif);"></div>
</div>
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);">
<div class="TableContentContainer">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody>
<tr>
<td class="LabelV"><b>Activate email code authentication for your account!</b>
<div style="float: right; font-size: 1px;">
<form action="{{ getLink('account/2fa') }}?action=email-code&step=activate" method="post" style="margin: 0; padding: 0;">
{{ csrf() }}
{% set button_name = 'Request' %}
{% include('buttons.base.html.twig') %}
</form>
</div>
</td>
</tr>
<tr>
<td>
<p>As a first step to activate <b>email code authentication</b> for your account, click on "Request"! An <b>email code</b> will be sent to the email address assigned to your account. You will be asked to enter this <b>email code</b> on the next page within 24 hours.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="TableShadowContainer">
<div class="TableBottomShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bm.gif);">
<div class="TableBottomLeftShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bl.gif);"></div>
<div class="TableBottomRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-br.gif);"></div>
</div>
</div>
</td>
</tr>

View File

@ -0,0 +1,26 @@
<tr>
<td>
<div class="TableContentContainer ">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody>
<tr>
<td>
<div style="float: right; width: 135px;">
<form action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="padding:0;margin:0;">
{{ csrf() }}
<input type="hidden" name="step" value="deactivate">
{% set button_name = 'Deactivate' %}
{{ include('buttons.base.html.twig') }}
</form>
</div>
<b>Two-Factor Email Code Authentication <span style="color: green">Activated</span>!</b>
<p>To deactivate <b>email code authentication</b>, click on the "Deactivate" button.</p>
<p>You will have to confirm the deactivation by entering an <b>email code</b> which will be sent
to the email address assigned to your account.</p>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>

View File

@ -31,9 +31,13 @@
<tr> <tr>
<td> <td>
<div style="float: right;"> <div style="float: right;">
<form action="{{ getLink('account/2fa') }}?action=emailcode&step=resend" <form action="{{ getLink('account/2fa') }}?action=email-code"
method="post" style="padding:0px;margin:0px;"> method="post" style="padding:0;margin:0;">
{{ set button_name = 'Resend Email Code' }} {{ csrf() }}
<input type="hidden" name="step" value="resend">
{% set button_name = 'Resend Email Code' %}
{% include('buttons.base.html.twig') %} {% include('buttons.base.html.twig') %}
</form> </form>
</div> </div>
@ -57,8 +61,13 @@
<td>To complete the activation of email code authentication for your Tibia account, please enter <td>To complete the activation of email code authentication for your Tibia account, please enter
the email code you received at the email address assigned to your account. the email code you received at the email address assigned to your account.
<div style="margin-top: 15px; margin-bottom: 15px;"> <div style="margin-top: 15px; margin-bottom: 15px;">
<div class="LabelV150" style="float:left;">Email Code:</div> <div class="LabelV150 {{ wrongCode ? 'red' : '' }}" style="float:left;">Email Code:</div>
<input form="confirmActivateForm" name="email-code" maxlength="15"> <input form="confirmActivateForm" name="email-code" maxlength="6">
{% if wrongCode %}
<br/>
<div class="LabelV150" style="float:left;">&nbsp; </div>
<div class="FormFieldError">Invalid email code!</div>
{% endif %}
</div> </div>
</td> </td>
</tr> </tr>
@ -70,18 +79,24 @@
</tbody> </tbody>
</table> </table>
{% endset %} {% endset %}
{% include 'tables.headline.html.twig' %}
<table style="width: 100%;"> <table style="width: 100%;">
<tbody> <tbody>
<tr align="center" valign="top"> <tr align="center" valign="top">
<td> <td>
<form id="confirmActivateForm" action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="padding:0;margin:0;"> <form id="confirmActivateForm" action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="padding:0;margin:0;">
<input type="hidden" name="step" value="confirm-activate"> {{ csrf() }}
<input type="hidden" name="step" value="activate">
<input type="hidden" name="save" value="1">
{% set button_color = 'green' %} {% set button_color = 'green' %}
{{ include('buttons.submit.html.twig') }} {{ include('buttons.submit.html.twig') }}
</form> </form>
</td> </td>
<td> <td>
<form action="{{ getLink('account/manage') }}" method="post" style="padding:0;margin:0;"> <form action="{{ getLink('account/manage') }}" method="post" style="padding:0;margin:0;">
{{ csrf() }}
{{ include('buttons.back.html.twig') }} {{ include('buttons.back.html.twig') }}
</form> </form>
</td> </td>

View File

@ -0,0 +1,12 @@
{% set title = 'Two-Factor Authentication' %}
{% set content %}
<table style="width:100%;">
<tbody>
{{ include(twoFactorViews[0]) }}
{{ include(twoFactorViews[1]) }}
</tbody>
</table>
{% endset %}
{% include('tables.headline.html.twig') %}
<br/>

View File

@ -0,0 +1,18 @@
<tr>
<td>
<div class="TableContentContainer ">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody>
<tr>
<td>
<div class="InTableRightButtonContainer"></div>
<b>Two-Factor Authenticator App</b>
<p>Your account is currently protected by email code authentication. If you prefer to use a <b>two-factor
authentication app</b>, you have to "Deactivate" email code authentication first.</p>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>

View File

@ -147,6 +147,9 @@
{% include('buttons.base.html.twig') %} {% include('buttons.base.html.twig') %}
</form> </form>
<br/> <br/>
{{ include('account.2fa.main.html.twig') }}
{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }} {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}
<a name="Account+Logs" ></a> <a name="Account+Logs" ></a>
<h2>Account Logs</h2> <h2>Account Logs</h2>

View File

@ -1,81 +0,0 @@
{% set title = 'Two-Factor Authentication' %}
{% set content %}
<table style="width:100%;">
<tbody>
<tr>
<td>
<div class="TableShadowContainerRightTop">
<div class="TableShadowRightTop" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rt.gif);"></div>
</div>
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);">
<div class="TableContentContainer">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody><tr>
<td class="LabelV"><b>Connect your {{ config.lua.serverName }} account to an authenticator app!</b>
<div style="float: right; font-size: 1px;">
<form action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="margin: 0px; padding: 0px;">
{{ csrf() }}
{% set button_name = 'Request' %}
{% include('buttons.base.html.twig') %}
</form>
</div>
</td>
</tr>
<tr>
<td>
<p>As a first step to connect an <b>authenticator app</b> to your account, click on "Request"! An email with a confirmation key will be sent to the email address assigned to your account.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="TableShadowContainer">
<div class="TableBottomShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bm.gif);">
<div class="TableBottomLeftShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bl.gif);"></div>
<div class="TableBottomRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-br.gif);"></div>
</div>
</div>
</td>
</tr>
<tr>
<td>
<div class="TableShadowContainerRightTop">
<div class="TableShadowRightTop" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rt.gif);"></div>
</div>
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);">
<div class="TableContentContainer">
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;">
<tbody><tr>
<td class="LabelV"><b>Activate email code authentication for your account!</b>
<div style="float: right; font-size: 1px;">
<form action="{{ getLink('account/2fa') }}?action=email-code" method="post" style="margin: 0; padding: 0;">
{{ csrf() }}
{% set button_name = 'Request' %}
{% include('buttons.base.html.twig') %}
</form>
</div>
</td>
</tr>
<tr>
<td>
<p>As a first step to activate <b>email code authentication</b> for your account, click on "Request"! An <b>email code</b> will be sent to the email address assigned to your account. You will be asked to enter this <b>email code</b> on the next page within 24 hours.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="TableShadowContainer">
<div class="TableBottomShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bm.gif);">
<div class="TableBottomLeftShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-bl.gif);"></div>
<div class="TableBottomRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-br.gif);"></div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
{% endset %}
{% include('tables.headline.html.twig') %}

View File

@ -290,6 +290,9 @@
{% endset %} {% endset %}
{% include 'tables.headline.html.twig' %} {% include 'tables.headline.html.twig' %}
<br/> <br/>
{{ include('account.2fa.main.html.twig') }}
{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }} {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }}
<a name="Account+Logs" ></a> <a name="Account+Logs" ></a>
<div class="TopButtonContainer"> <div class="TopButtonContainer">