mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Template/Update (Part 46 - IV)
* account management rework: Personal Settings functionality * email, password, username update * email updates now also mails the old address for confirmation
This commit is contained in:
@@ -24,6 +24,7 @@ Also, this project is not meant to be used for commercial purposes of any kind!
|
||||
+ [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php)
|
||||
+ [Multibyte String](https://www.php.net/manual/en/book.mbstring.php)
|
||||
+ [File Information](https://www.php.net/manual/en/book.fileinfo.php)
|
||||
+ [Internationalization](https://www.php.net/manual/en/book.intl.php)
|
||||
+ [GNU Multiple Precision](https://www.php.net/manual/en/book.gmp.php) (When using TrinityCore as auth source)
|
||||
+ MySQL ≥ 5.7.0 OR MariaDB ≥ 10.6.4 OR similar
|
||||
+ [TDB 335.21101](https://github.com/TrinityCore/TrinityCore/releases/tag/TDB335.21101) (no other other providers are supported at this time)
|
||||
|
||||
@@ -28,6 +28,7 @@ class AccountBaseResponse extends TemplateResponse
|
||||
public string $curEmail = '';
|
||||
public string $curName = '';
|
||||
public string $renameCD = '';
|
||||
public string $activeCD = '';
|
||||
public array $description = [];
|
||||
public array $signature = [];
|
||||
public int $avMode = 0;
|
||||
@@ -51,7 +52,7 @@ class AccountBaseResponse extends TemplateResponse
|
||||
{
|
||||
array_unshift($this->title, Lang::account('settings'));
|
||||
|
||||
$user = DB::Aowow()->selectRow('SELECT `debug`, `email`, `description`, `avatar`, `wowicon` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||
$user = DB::Aowow()->selectRow('SELECT `debug`, `email`, `description`, `avatar`, `wowicon`, `renameCooldown` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||
|
||||
Lang::sort('game', 'ra');
|
||||
|
||||
@@ -109,9 +110,12 @@ class AccountBaseResponse extends TemplateResponse
|
||||
|
||||
// Username
|
||||
$this->curName = User::$username;
|
||||
|
||||
// todo localize date format; store time
|
||||
// $this->renameCD = date('F j, o', time() + 7 * DAY);
|
||||
$this->renameCD = Util::formatTime(Cfg::get('ACC_RENAME_DECAY') * 1000);
|
||||
if ($user['renameCooldown'] > time())
|
||||
{
|
||||
$locCode = implode('_', str_split(Lang::getLocale()->json(), 2)); // ._.
|
||||
$this->activeCD = (new \IntlDateFormatter($locCode, pattern: Lang::main('dateFmtIntl')))->format($user['renameCooldown']);
|
||||
}
|
||||
|
||||
/* COMMUNITY */
|
||||
|
||||
|
||||
62
endpoints/account/confirm-email-address.php
Normal file
62
endpoints/account/confirm-email-address.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
/*
|
||||
* accessed via confirmation email link
|
||||
* write status to session and redirect to account settings
|
||||
*/
|
||||
|
||||
// ?auth=email-change
|
||||
class AccountConfirmemailaddressResponse extends TemplateResponse
|
||||
{
|
||||
protected string $template = 'text-page-generic';
|
||||
protected string $pageName = 'confirm-email-address';
|
||||
|
||||
protected array $expectedGET = array(
|
||||
'key' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']]
|
||||
);
|
||||
|
||||
private bool $success = false;
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
parent::generate();
|
||||
|
||||
if (User::isBanned())
|
||||
return;
|
||||
|
||||
$msg = $this->change();
|
||||
|
||||
$this->inputbox = ['inputbox-status', array(
|
||||
'head' => Lang::account('inputbox', 'head', $this->success ? 'success' : 'error'),
|
||||
'message' => $this->success ? $msg : '',
|
||||
'error' => $this->success ? '' : $msg,
|
||||
)];
|
||||
}
|
||||
|
||||
// this should probably leave change info intact for revert
|
||||
// todo - move personal settings changes to separate table
|
||||
private function change() : string
|
||||
{
|
||||
if (!$this->assertGET('key'))
|
||||
return Lang::main('intError');
|
||||
|
||||
$acc = DB::Aowow()->selectRow('SELECT `updateValue`, `status`, `statusTimer` FROM ?_account WHERE `token` = ?', $this->_get['key']);
|
||||
if (!$acc || $acc['status'] != ACC_STATUS_CHANGE_EMAIL || $acc['statusTimer'] < time())
|
||||
return Lang::account('inputbox', 'error', 'mailTokenUsed');
|
||||
|
||||
// 0 changes == error
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET `email` = `updateValue`, `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "" WHERE `token` = ?', ACC_STATUS_NONE, $this->_get['key']))
|
||||
return Lang::main('intError');
|
||||
|
||||
$this->success = true;
|
||||
return Lang::account('inputbox', 'message', 'mailChangeOk');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
60
endpoints/account/confirm-password.php
Normal file
60
endpoints/account/confirm-password.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
/*
|
||||
* accessed via confirmation email link
|
||||
* write status to session and redirect to account settings
|
||||
*/
|
||||
|
||||
// 2025 - no longer in use?
|
||||
class AccountConfirmpasswordResponse extends TemplateResponse
|
||||
{
|
||||
protected string $template = 'text-page-generic';
|
||||
protected string $pageName = 'confirm-password';
|
||||
|
||||
protected array $expectedGET = array(
|
||||
'key' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']]
|
||||
);
|
||||
|
||||
private bool $success = false;
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
parent::generate();
|
||||
|
||||
if (User::isBanned())
|
||||
return;
|
||||
|
||||
$msg = $this->confirm();
|
||||
|
||||
$this->inputbox = ['inputbox-status', array(
|
||||
'head' => Lang::account('inputbox', 'head', $this->success ? 'success' : 'error'),
|
||||
'message' => $this->success ? $msg : '',
|
||||
'error' => $this->success ? '' : $msg,
|
||||
)];
|
||||
}
|
||||
|
||||
private function confirm() : string
|
||||
{
|
||||
if (!$this->assertGET('key'))
|
||||
return Lang::main('intError');
|
||||
|
||||
$acc = DB::Aowow()->selectRow('SELECT `updateValue`, `status`, `statusTimer` FROM ?_account WHERE `token` = ?', $this->_get['key']);
|
||||
if (!$acc || $acc['status'] != ACC_STATUS_CHANGE_PASS || $acc['statusTimer'] < time())
|
||||
return Lang::account('inputbox', 'error', 'passTokenUsed');
|
||||
|
||||
// 0 changes == error
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET `passHash` = `updateValue`, `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "" WHERE `token` = ?', ACC_STATUS_NONE, $this->_get['key']))
|
||||
return Lang::main('intError');
|
||||
|
||||
$this->success = true;
|
||||
return Lang::account('inputbox', 'message', 'passChangeOk');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
62
endpoints/account/revert-email-address.php
Normal file
62
endpoints/account/revert-email-address.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
/*
|
||||
* accessed via revert email link
|
||||
* write status to session and redirect to account settings
|
||||
*/
|
||||
|
||||
// ?auth=email-revert
|
||||
class AccountRevertemailaddressResponse extends TemplateResponse
|
||||
{
|
||||
protected string $template = 'text-page-generic';
|
||||
protected string $pageName = 'revert-email-address';
|
||||
|
||||
protected array $expectedGET = array(
|
||||
'key' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']]
|
||||
);
|
||||
|
||||
private bool $success = false;
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
parent::generate();
|
||||
|
||||
if (User::isBanned())
|
||||
return;
|
||||
|
||||
$msg = $this->revert();
|
||||
|
||||
$this->inputbox = ['inputbox-status', array(
|
||||
'head' => Lang::account('inputbox', 'head', $this->success ? 'success' : 'error'),
|
||||
'message' => $this->success ? $msg : '',
|
||||
'error' => $this->success ? '' : $msg,
|
||||
)];
|
||||
}
|
||||
|
||||
// this should probably take precedence over email-change
|
||||
// todo - move personal settings changes to separate table
|
||||
private function revert() : string
|
||||
{
|
||||
if (!$this->assertGET('key'))
|
||||
return Lang::main('intError');
|
||||
|
||||
$acc = DB::Aowow()->selectRow('SELECT `updateValue`, `status`, `statusTimer` FROM ?_account WHERE `token` = ?', $this->_get['key']);
|
||||
if (!$acc || $acc['status'] != ACC_STATUS_CHANGE_EMAIL || $acc['statusTimer'] < time())
|
||||
return Lang::account('inputbox', 'error', 'mailTokenUsed');
|
||||
|
||||
// 0 changes == error
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "" WHERE `token` = ?', ACC_STATUS_NONE, $this->_get['key']))
|
||||
return Lang::main('intError');
|
||||
|
||||
$this->success = true;
|
||||
return Lang::account('inputbox', 'message', 'mailRevertOk');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
80
endpoints/account/update-email.php
Normal file
80
endpoints/account/update-email.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
/*
|
||||
* accessed via account settings form submit
|
||||
* write status to session and redirect to account settings
|
||||
*/
|
||||
|
||||
class AccountUpdateemailResponse extends TextResponse
|
||||
{
|
||||
protected ?string $redirectTo = '?account#personal';
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'newemail' => ['filter' => FILTER_VALIDATE_EMAIL, 'flags' => FILTER_FLAG_STRIP_AOWOW]
|
||||
);
|
||||
|
||||
private bool $success = false;
|
||||
|
||||
public function __construct(string $pageParam)
|
||||
{
|
||||
if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF)
|
||||
(new TemplateResponse())->generateError();
|
||||
|
||||
parent::__construct($pageParam);
|
||||
}
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (User::isBanned())
|
||||
return;
|
||||
|
||||
if ($msg = $this->updateMail())
|
||||
$_SESSION['msg'] = ['email', $this->success, $msg];
|
||||
}
|
||||
|
||||
private function updateMail() : string
|
||||
{
|
||||
// no input yet
|
||||
if (is_null($this->_post['newemail']))
|
||||
return Lang::main('intError');
|
||||
// truncated due to validation fail
|
||||
if (!$this->_post['newemail'])
|
||||
return Lang::account('emailInvalid');
|
||||
|
||||
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE `email` = ? AND `id` <> ?d', $this->_post['newemail'], User::$id))
|
||||
return Lang::account('mailInUse');
|
||||
|
||||
$status = DB::Aowow()->selectCell('SELECT `status` FROM ?_account WHERE `statusTimer` > UNIX_TIMESTAMP() AND `id` = ?d', User::$id);
|
||||
if ($status != ACC_STATUS_NONE && $status != ACC_STATUS_CHANGE_EMAIL)
|
||||
return Lang::account('isRecovering', [Util::formatTime(Cfg::get('ACC_RECOVERY_DECAY') * 1000)]);
|
||||
|
||||
$oldEmail = DB::Aowow()->selectCell('SELECT `email` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||
if ($this->_post['newemail'] == $oldEmail)
|
||||
return Lang::account('newMailDiff');
|
||||
|
||||
$token = Util::createHash();
|
||||
|
||||
// store new mail in updateValue field, exchange when confirmation mail gets confirmed
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET `updateValue` = ?, `status` = ?d, `statusTimer` = UNIX_TIMESTAMP() + ?d, `token` = ? WHERE `id` = ?d',
|
||||
$this->_post['newemail'], ACC_STATUS_CHANGE_EMAIL, Cfg::get('ACC_RECOVERY_DECAY'), $token, User::$id))
|
||||
return Lang::main('intError');
|
||||
|
||||
if (!Util::sendMail($this->_post['newemail'], 'change-email', [$token, $this->_post['newemail']], Cfg::get('ACC_RECOVERY_DECAY')))
|
||||
return Lang::main('intError2', ['send mail']);
|
||||
|
||||
if (!Util::sendMail($oldEmail, 'revert-email', [$token, $oldEmail], Cfg::get('ACC_RECOVERY_DECAY')))
|
||||
return Lang::main('intError2', ['send mail']);
|
||||
|
||||
$this->success = true;
|
||||
return Lang::account('updateMessage', 'personal', [$this->_post['newemail']]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
86
endpoints/account/update-password.php
Normal file
86
endpoints/account/update-password.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
/*
|
||||
* accessed via account settings form submit
|
||||
* write status to session and redirect to account settings
|
||||
*/
|
||||
|
||||
class AccountUpdatepasswordResponse extends TextResponse
|
||||
{
|
||||
protected ?string $redirectTo = '?account#personal';
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'currentPassword' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine']],
|
||||
'newPassword' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine']],
|
||||
'confirmPassword' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine']],
|
||||
'globalLogout' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkCheckbox']]
|
||||
);
|
||||
|
||||
private bool $success = false;
|
||||
|
||||
public function __construct(string $pageParam)
|
||||
{
|
||||
if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF)
|
||||
(new TemplateResponse())->generateError();
|
||||
|
||||
parent::__construct($pageParam);
|
||||
}
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (User::isBanned())
|
||||
return;
|
||||
|
||||
if ($msg = $this->updatePassword())
|
||||
$_SESSION['msg'] = ['password', $this->success, $msg];
|
||||
}
|
||||
|
||||
private function updatePassword() : string
|
||||
{
|
||||
if (!$this->assertPOST('currentPassword', 'newPassword', 'confirmPassword'))
|
||||
return Lang::main('intError');
|
||||
|
||||
if (!Util::validatePassword($this->_post['newPassword'], $e))
|
||||
return Lang::account($e == 1 ? 'errPassLength' : 'errPassChars');
|
||||
|
||||
if ($this->_post['newPassword'] !== $this->_post['confirmPassword'])
|
||||
return Lang::account('passMismatch');
|
||||
|
||||
$userData = DB::Aowow()->selectRow('SELECT `status`, `passHash`, `statusTimer` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||
if ($userData['status'] != ACC_STATUS_NONE && $userData['status'] != ACC_STATUS_CHANGE_PASS && $userData['statusTimer'] > time())
|
||||
return Lang::account('isRecovering', [Util::formatTime(Cfg::get('ACC_RECOVERY_DECAY') * 1000)]);
|
||||
|
||||
if (!User::verifyCrypt($this->_post['currentPassword'], $userData['passHash']))
|
||||
return Lang::account('wrongPass');
|
||||
|
||||
if (User::verifyCrypt($this->_post['newPassword'], $userData['passHash']))
|
||||
return Lang::account('newPassDiff');
|
||||
|
||||
$token = Util::createHash();
|
||||
|
||||
// store new hash in updateValue field, exchange when confirmation mail gets confirmed
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET `updateValue` = ?, `status` = ?d, `statusTimer` = UNIX_TIMESTAMP() + ?d, `token` = ? WHERE `id` = ?d',
|
||||
User::hashCrypt($this->_post['newPassword']), ACC_STATUS_CHANGE_PASS, Cfg::get('ACC_RECOVERY_DECAY'), $token, User::$id))
|
||||
return Lang::main('intError');
|
||||
|
||||
$email = DB::Aowow()->selectCell('SELECT `email` FROM ?_account WHERE `id` = ?d', User::$id);
|
||||
if (!Util::sendMail($email, 'update-password', [$token, $email], Cfg::get('ACC_RECOVERY_DECAY')))
|
||||
return Lang::main('intError2', ['send mail']);
|
||||
|
||||
// logout all other active sessions
|
||||
if ($this->_post['globalLogout'])
|
||||
DB::Aowow()->query('UPDATE ?_account_sessions SET `status` = ?d, `touched` = ?d WHERE `userId` = ?d AND `sessionId` <> ? AND `status` = ?d', SESSION_FORCED_LOGOUT, time(), User::$id, session_id(), SESSION_ACTIVE);
|
||||
|
||||
$this->success = true;
|
||||
return Lang::account('updateMessage', 'personal', [User::$email]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
61
endpoints/account/update-username.php
Normal file
61
endpoints/account/update-username.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
/*
|
||||
* accessed via account settings form submit
|
||||
* write status to session and redirect to account settings
|
||||
*/
|
||||
|
||||
class AccountUpdateusernameResponse extends TextResponse
|
||||
{
|
||||
protected ?string $redirectTo = '?account#personal';
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'newUsername' => ['filter' => FILTER_CALLBACK, 'options' => [Util::class, 'validateUsername']]
|
||||
);
|
||||
|
||||
private bool $success = false;
|
||||
|
||||
public function __construct(string $pageParam)
|
||||
{
|
||||
if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF)
|
||||
(new TemplateResponse())->generateError();
|
||||
|
||||
parent::__construct($pageParam);
|
||||
}
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (User::isBanned())
|
||||
return;
|
||||
|
||||
if ($msg = $this->updateUsername())
|
||||
$_SESSION['msg'] = ['username', $this->success, $msg];
|
||||
}
|
||||
|
||||
private function updateUsername() : string
|
||||
{
|
||||
if (!$this->assertPOST('newUsername'))
|
||||
return Lang::main('intError');
|
||||
|
||||
if (DB::Aowow()->selectCell('SELECT `renameCooldown` FROM ?_account WHERE `id` = ?d', User::$id) > time())
|
||||
return Lang::main('intError'); // should have grabbed the error response..
|
||||
|
||||
// yes, including your current name. you don't want to change into your current name, right?
|
||||
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE LOWER(`username`) = LOWER(?)', $this->_post['newUsername']))
|
||||
return Lang::account('nameInUse');
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_account SET `username` = ?, `renameCooldown` = ?d WHERE `id` = ?d', $this->_post['newUsername'], time() + Cfg::get('acc_rename_decay'), User::$id);
|
||||
|
||||
$this->success = true;
|
||||
return Lang::account('updateMessage', 'username', [User::$username, $this->_post['newUsername']]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -13,7 +13,7 @@ define('CLI_HAS_E', CLI && // WIN10 and later u
|
||||
(!OS_WIN || (function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT))));
|
||||
|
||||
|
||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'/*, 'gmp'*/];
|
||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo', 'intl'/*, 'gmp'*/];
|
||||
$badExt = [];
|
||||
$error = '';
|
||||
if ($ext = array_filter($reqExt, fn($x) => !extension_loaded($x)))
|
||||
|
||||
@@ -133,7 +133,7 @@ $lang = array(
|
||||
'colon' => ': ',
|
||||
'dateFmtShort' => "d.m.Y",
|
||||
'dateFmtLong' => "d.m.Y \u\m H:i",
|
||||
'dateFmtUntil' => "j. F Y",
|
||||
'dateFmtIntl' => "d. MMMM y",
|
||||
'timeAgo' => 'vor %s',
|
||||
'nfSeparators' => ['.', ','],
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ $lang = array(
|
||||
'colon' => ': ',
|
||||
'dateFmtShort' => "Y/m/d",
|
||||
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
||||
'dateFmtUntil' => "F j, Y",
|
||||
'dateFmtIntl' => "MMMM d, y",
|
||||
'timeAgo' => "%s ago",
|
||||
'nfSeparators' => [',', '.'],
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ $lang = array(
|
||||
'colon' => ': ',
|
||||
'dateFmtShort' => "d/m/Y",
|
||||
'dateFmtLong' => "d/m/Y \a \l\a\s g:i A",
|
||||
'dateFmtUntil' => "j \d\\e F \d\\e Y",
|
||||
'dateFmtIntl' => "d 'de' MMMM 'de' y",
|
||||
'timeAgo' => 'hace %s',
|
||||
'nfSeparators' => ['.', ','],
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ $lang = array(
|
||||
'colon' => ' : ',
|
||||
'dateFmtShort' => "Y-m-d",
|
||||
'dateFmtLong' => "Y-m-d à g:i A",
|
||||
'dateFmtUntil' => "j F Y",
|
||||
'dateFmtIntl' => "d MMMM y",
|
||||
'timeAgo' => 'il y a %s',
|
||||
'nfSeparators' => [' ', ','],
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ $lang = array(
|
||||
'colon' => ": ",
|
||||
'dateFmtShort' => "Y-m-d",
|
||||
'dateFmtLong' => "Y-m-d в g:i A",
|
||||
'dateFmtUntil' => "j F Y г.",
|
||||
'dateFmtIntl' => "d MMMM y г.",
|
||||
'timeAgo' => '%s назад',
|
||||
'nfSeparators' => [' ', ','],
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ $lang = array(
|
||||
'colon' => ':',
|
||||
'dateFmtShort' => "Y/m/d",
|
||||
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
||||
'dateFmtUntil' => "Y年n月j日",
|
||||
'dateFmtIntl' => "y年M月d日",
|
||||
'timeAgo' => '%s之前',
|
||||
'nfSeparators' => [',', '.'],
|
||||
|
||||
|
||||
2
setup/updates/1758578400_13.sql
Normal file
2
setup/updates/1758578400_13.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `aowow_account`
|
||||
ADD COLUMN `renameCooldown` int unsigned NOT NULL DEFAULT 0 COMMENT 'timestamp when rename is available again' AFTER `updateValue`;
|
||||
2
setup/updates/1758578400_14.sql
Normal file
2
setup/updates/1758578400_14.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
DELETE FROM `aowow_config` WHERE `key` = 'acc_rename_decay';
|
||||
INSERT INTO `aowow_config` VALUES ('acc_rename_decay', 30 * 24 * 60 * 60, '30 * 24 * 60 * 60', 3, 129, 'delay between username changes');
|
||||
11
template/mails/change-email_0.tpl
Normal file
11
template/mails/change-email_0.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# Created: 2025
|
||||
Email Change Confirm
|
||||
Greetings,
|
||||
|
||||
We received a request to change your account's email address. If you made this request, please follow the link below to confirm the change.
|
||||
|
||||
HOST_URL?account=confirm-email-address&key=%1$s
|
||||
|
||||
If you didn't request this change please feel free to disregard this email. If the link did not work or you have any further concerns about this, please contact CONTACT_EMAIL. The link will become invalid %10$s after this email was sent.
|
||||
|
||||
The NAME_SHORT team
|
||||
11
template/mails/change-email_2.tpl
Normal file
11
template/mails/change-email_2.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
Demande de confirmation de changement d'adresse e-mail
|
||||
Bonjour,
|
||||
|
||||
Nous avons reçu une demande de modification de l'adresse e-mail associée à votre compte. Si vous êtes à l'origine de cette demande, veuillez suivre le lien ci-dessous pour confirmer le changement.
|
||||
|
||||
HOST_URL?account=confirm-email-address&key=%1$s
|
||||
|
||||
Si vous n'avez pas demandé ce changement, vous pouvez ignorer cet e-mail. Si le lien ne fonctionne pas ou si vous avez d'autres préoccupations à ce sujet, veuillez contacter CONTACT_EMAIL. Ce lien deviendra invalide %10$s après l'envoi de cet e-mail.
|
||||
|
||||
L'équipe NAME_SHORT
|
||||
11
template/mails/change-email_3.tpl
Normal file
11
template/mails/change-email_3.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
Bestätigung der E-Mail-Änderung angefordert
|
||||
Hallo,
|
||||
|
||||
Wir haben eine Anfrage zur Änderung Ihrer E-Mail-Adresse erhalten. Wenn Sie diese Anfrage gestellt haben, folgen Sie bitte dem untenstehenden Link, um die Änderung zu bestätigen.
|
||||
|
||||
HOST_URL?account=confirm-email-address&key=%1$s
|
||||
|
||||
Falls Sie diese Änderung nicht angefordert haben, können Sie diese E-Mail ignorieren. Falls der Link nicht funktioniert oder Sie weitere Fragen haben, wenden Sie sich bitte an CONTACT_EMAIL. Der Link wird %10$s nach Versand dieser E-Mail ungültig.
|
||||
|
||||
Das Team von NAME_SHORT
|
||||
11
template/mails/change-email_4.tpl
Normal file
11
template/mails/change-email_4.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
确认更改电子邮件地址
|
||||
您好,
|
||||
|
||||
我们收到了一项更改您账户电子邮件地址的请求。如果是您本人操作,请点击下方链接以确认更改。
|
||||
|
||||
HOST_URL?account=confirm-email-address&key=%1$s
|
||||
|
||||
如果您未曾发起此更改,请忽略此邮件。如果链接无法使用或您对此有任何疑问,请联系 CONTACT_EMAIL。此链接将在本邮件发送后 %10$s 失效。
|
||||
|
||||
NAME_SHORT 团队敬上
|
||||
11
template/mails/change-email_6.tpl
Normal file
11
template/mails/change-email_6.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
Confirmación de cambio de correo electrónico
|
||||
Saludos,
|
||||
|
||||
Hemos recibido una solicitud para cambiar la dirección de correo electrónico de su cuenta. Si usted realizó esta solicitud, siga el enlace de abajo para confirmar el cambio.
|
||||
|
||||
HOST_URL?account=confirm-email-address&key=%1$s
|
||||
|
||||
Si usted no solicitó este cambio, puede ignorar este correo. Si el enlace no funciona o tiene alguna inquietud, por favor contacte a CONTACT_EMAIL. El enlace se invalidará %10$s después de que este correo haya sido enviado.
|
||||
|
||||
El equipo de NAME_SHORT
|
||||
12
template/mails/change-email_8.tpl
Normal file
12
template/mails/change-email_8.tpl
Normal file
@@ -0,0 +1,12 @@
|
||||
# GPTed from 2025 source
|
||||
Подтверждение изменения адреса электронной почты
|
||||
Здравствуйте,
|
||||
|
||||
Мы получили запрос на изменение адреса электронной почты, связанного с вашим аккаунтом. Если вы отправили этот запрос, пожалуйста, перейдите по ссылке ниже для подтверждения изменения.
|
||||
|
||||
HOST_URL?account=confirm-email-address&key=%1$s
|
||||
|
||||
Если вы не запрашивали это изменение, просто проигнорируйте это письмо. Если ссылка не работает или у вас есть дополнительные вопросы, пожалуйста, свяжитесь с CONTACT_EMAIL. Ссылка станет недействительной через %10$s после отправки этого письма.
|
||||
|
||||
Команда NAME_SHORT
|
||||
Пожалуйста, перейдите по ссылке ниже, чтобы подтвердить ваш новый адрес электронной почты.
|
||||
11
template/mails/revert-email_0.tpl
Normal file
11
template/mails/revert-email_0.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# Created: 2025
|
||||
Email Change Requested
|
||||
Greetings,
|
||||
|
||||
We received a request to change your account's email address. If you made this request, please follow the instructions in the confirmation email sent to the address indicated. If you didn't make such a request, please click the link below to prevent the email from being changed.
|
||||
|
||||
HOST_URL?account=revert-email-address&key=%1$s
|
||||
|
||||
If the link did not work or you have any further concerns about this, please contact CONTACT_EMAIL. This link will automatically become invalid %10$s from now.
|
||||
|
||||
The NAME_SHORT team
|
||||
11
template/mails/revert-email_2.tpl
Normal file
11
template/mails/revert-email_2.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
Demande de modification d'adresse e-mail
|
||||
Bonjour,
|
||||
|
||||
Nous avons reçu une demande de modification de l'adresse e-mail associée à votre compte. Si vous êtes à l'origine de cette demande, veuillez suivre les instructions contenues dans l'e-mail de confirmation envoyé à l'adresse indiquée. Si vous n'êtes pas à l'origine de cette demande, veuillez cliquer sur le lien ci-dessous pour empêcher la modification de l'adresse e-mail.
|
||||
|
||||
HOST_URL?account=revert-email-address&key=%1$s
|
||||
|
||||
Si le lien ne fonctionne pas ou si vous avez d'autres préoccupations à ce sujet, veuillez contacter CONTACT_EMAIL. Ce lien deviendra automatiquement invalide dans %10$s.
|
||||
|
||||
L'équipe NAME_SHORT
|
||||
11
template/mails/revert-email_3.tpl
Normal file
11
template/mails/revert-email_3.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
E-Mail-Änderung angefordert
|
||||
Hallo,
|
||||
|
||||
Wir haben eine Anfrage zur Änderung Ihrer E-Mail-Adresse erhalten. Wenn Sie diese Anfrage gestellt haben, folgen Sie bitte den Anweisungen in der Bestätigungs-E-Mail, die an die angegebene Adresse gesendet wurde. Falls Sie diese Anfrage nicht gestellt haben, klicken Sie bitte auf den untenstehenden Link, um die Änderung der E-Mail-Adresse zu verhindern.
|
||||
|
||||
HOST_URL?account=revert-email-address&key=%1$s
|
||||
|
||||
Falls der Link nicht funktioniert oder Sie weitere Fragen haben, wenden Sie sich bitte an CONTACT_EMAIL. Dieser Link wird automatisch nach %%10$s ungültig.
|
||||
|
||||
Ihr NAME_SHORT-Team
|
||||
11
template/mails/revert-email_4.tpl
Normal file
11
template/mails/revert-email_4.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
请求更改电子邮件地址
|
||||
您好,
|
||||
|
||||
我们收到了一项更改您账户电子邮件地址的请求。如果是您本人操作,请按照发送到指定地址的确认邮件中的说明进行操作。如果不是您本人操作,请点击下方链接以阻止电子邮件地址的更改。
|
||||
|
||||
HOST_URL?account=revert-email-address&key=%1$s
|
||||
|
||||
如果链接无法使用或您对此有任何疑问,请联系 CONTACT_EMAIL。此链接将在 %10$s 后自动失效。
|
||||
|
||||
NAME_SHORT 团队敬上
|
||||
11
template/mails/revert-email_6.tpl
Normal file
11
template/mails/revert-email_6.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
Solicitud de cambio de correo electrónico
|
||||
Saludos,
|
||||
|
||||
Hemos recibido una solicitud para cambiar la dirección de correo electrónico de su cuenta. Si usted realizó esta solicitud, siga las instrucciones en el correo de confirmación enviado a la dirección indicada. Si no realizó esta solicitud, haga clic en el enlace de abajo para evitar el cambio de correo electrónico.
|
||||
|
||||
HOST_URL?account=revert-email-address&key=%1$s
|
||||
|
||||
Si el enlace no funciona o tiene alguna inquietud, por favor contacte a CONTACT_EMAIL. Este enlace se invalidará automáticamente en %10$s.
|
||||
|
||||
El equipo de NAME_SHORT
|
||||
11
template/mails/revert-email_8.tpl
Normal file
11
template/mails/revert-email_8.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
# GPTed from 2025 source
|
||||
Запрос на изменение адреса электронной почты
|
||||
Здравствуйте,
|
||||
|
||||
Мы получили запрос на изменение адреса электронной почты, связанного с вашим аккаунтом. Если вы отправили этот запрос, пожалуйста, следуйте инструкциям в письме с подтверждением, отправленном на указанный адрес. Если вы не отправляли такой запрос, пожалуйста, перейдите по ссылке ниже, чтобы предотвратить изменение адреса электронной почты.
|
||||
|
||||
HOST_URL?account=revert-email-address&key=%1$s
|
||||
|
||||
Если ссылка не работает или у вас есть дополнительные вопросы, пожалуйста, свяжитесь с CONTACT_EMAIL. Эта ссылка автоматически станет недействительной через %10$s.
|
||||
|
||||
Команда NAME_SHORT
|
||||
10
template/mails/update-password_0.tpl
Normal file
10
template/mails/update-password_0.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
# Created: May 2025
|
||||
Password Confirmation
|
||||
Hey!
|
||||
|
||||
Please click the link below to confirm your new password.
|
||||
HOST_URL?account=confirm-password&key=%1$s
|
||||
|
||||
Let us know if you have any problems!
|
||||
|
||||
The NAME_SHORT team
|
||||
10
template/mails/update-password_2.tpl
Normal file
10
template/mails/update-password_2.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
# Created: May 2025
|
||||
Confirmation du mot de passe
|
||||
Bonjour !
|
||||
|
||||
Veuillez cliquer sur le lien ci-dessous pour confirmer votre nouveau mot de passe.
|
||||
HOST_URL?account=confirm-password&key=%1$s
|
||||
|
||||
Faites-nous savoir si vous rencontrez des problèmes !
|
||||
|
||||
L'équipe NAME_SHORT
|
||||
10
template/mails/update-password_3.tpl
Normal file
10
template/mails/update-password_3.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
# Created: May 2025
|
||||
Passwortbestätigung
|
||||
Hallo!
|
||||
|
||||
Bitte klicke auf den untenstehenden Link, um dein neues Passwort zu bestätigen.
|
||||
HOST_URL?account=confirm-password&key=%1$s
|
||||
|
||||
Lass uns wissen, falls du Probleme hast!
|
||||
|
||||
Das NAME_SHORT Team
|
||||
10
template/mails/update-password_4.tpl
Normal file
10
template/mails/update-password_4.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
# Created by ChatGPT from May 2025 base; locale 0
|
||||
密码确认
|
||||
你好!
|
||||
|
||||
请点击下面的链接以确认你的新密码。
|
||||
HOST_URL?account=confirm-password&key=%1$s
|
||||
|
||||
如果你有任何问题,请告诉我们!
|
||||
|
||||
NAME_SHORT 团队敬上
|
||||
10
template/mails/update-password_6.tpl
Normal file
10
template/mails/update-password_6.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
# Created: May 2025
|
||||
Confirmación de contraseña
|
||||
¡Hola!
|
||||
|
||||
Por favor, haz clic en el siguiente enlace para confirmar tu nueva contraseña.
|
||||
HOST_URL?account=confirm-password&key=%1$s
|
||||
|
||||
¡Avísanos si tienes algún problema!
|
||||
|
||||
El equipo de NAME_SHORT
|
||||
10
template/mails/update-password_8.tpl
Normal file
10
template/mails/update-password_8.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
# Created: May 2025
|
||||
Подтверждение пароля
|
||||
Здравствуйте!
|
||||
|
||||
Пожалуйста, перейдите по ссылке ниже, чтобы подтвердить ваш новый пароль.
|
||||
HOST_URL?account=confirm-password&key=%1$s
|
||||
|
||||
Сообщите нам, если у вас возникнут какие-либо проблемы!
|
||||
|
||||
Команда NAME_SHORT
|
||||
@@ -110,9 +110,9 @@ if ($this->bans):
|
||||
<div class="box"><div class="msg-<?=($type ? 'success' : 'failure');?>"><?=$msg;?></div></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div><?=Lang::account('usernameNote');?></div>
|
||||
<?php if ($this->renameCD): ?>
|
||||
<div class="msg-failure pad3"><br /><?=Lang::account('renameCD', [$this->renameCD]);?></div>
|
||||
<div><?=Lang::account('usernameNote', [$this->renameCD]);?></div>
|
||||
<?php if ($this->activeCD): ?>
|
||||
<div class="msg-failure pad3"><br /><?=Lang::account('activeCD', [$this->activeCD]);?></div>
|
||||
<?php endif; ?>
|
||||
<form action="?account=update-username" name="ce" method="post" id="change-username">
|
||||
<table cellspacing="5" cellpadding="0" border="0">
|
||||
|
||||
Reference in New Issue
Block a user