mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
User/Sessions
* implement tracking
* FUTURE: log out all devices for user
* generally store less info in _SESSION
This commit is contained in:
@@ -204,7 +204,7 @@ class Report
|
||||
'subject' => $this->subject,
|
||||
'ip' => User::$ip,
|
||||
'description' => $desc,
|
||||
'userAgent' => $userAgent ?: $_SERVER['HTTP_USER_AGENT'],
|
||||
'userAgent' => $userAgent ?: User::$agent,
|
||||
'appName' => $appName ?: (get_browser(null, true)['browser'] ?: '')
|
||||
);
|
||||
|
||||
|
||||
@@ -68,6 +68,12 @@ define('ACC_STATUS_NEW', 1); // just created, awa
|
||||
define('ACC_STATUS_RECOVER_USER', 2); // currently recovering username
|
||||
define('ACC_STATUS_RECOVER_PASS', 3); // currently recovering password
|
||||
|
||||
// Session Status
|
||||
define('SESSION_ACTIVE', 1);
|
||||
define('SESSION_LOGOUT', 2);
|
||||
define('SESSION_FORCED_LOGOUT', 3);
|
||||
define('SESSION_EXPIRED', 4);
|
||||
|
||||
define('ACC_BAN_NONE', 0x00); // all clear
|
||||
define('ACC_BAN_TEMP', 0x01);
|
||||
define('ACC_BAN_PERM', 0x02);
|
||||
|
||||
@@ -10,18 +10,19 @@ class User
|
||||
{
|
||||
public static int $id = 0;
|
||||
public static string $username = '';
|
||||
public static int $banStatus = 0x0; // see ACC_BAN_* defines
|
||||
public static int $banStatus = 0x0; // see ACC_BAN_* defines
|
||||
public static int $status = 0x0;
|
||||
public static int $groups = 0x0;
|
||||
public static int $perms = 0;
|
||||
public static ?string $email = null;
|
||||
public static int $dailyVotes = 0;
|
||||
public static bool $debug = false; // show ids in lists (used to be debug, is now user setting)
|
||||
public static ?string $ip = null;
|
||||
public static ?string $agent = null;
|
||||
public static Locale $preferedLoc;
|
||||
|
||||
private static int $reputation = 0;
|
||||
private static string $dataKey = '';
|
||||
private static bool $expires = false;
|
||||
private static string $passHash = '';
|
||||
private static int $excludeGroups = 1;
|
||||
private static ?LocalProfileList $profiles = null;
|
||||
|
||||
@@ -38,9 +39,10 @@ class User
|
||||
|
||||
// session have a dataKey to access the JScripts (yes, also the anons)
|
||||
if (empty($_SESSION['dataKey']))
|
||||
$_SESSION['dataKey'] = Util::createHash(); // just some random numbers for identifictaion purpose
|
||||
$_SESSION['dataKey'] = Util::createHash(); // just some random numbers for identification purpose
|
||||
|
||||
self::$dataKey = $_SESSION['dataKey'];
|
||||
self::$agent = $_SERVER['HTTP_USER_AGENT'];
|
||||
|
||||
if (!self::$ip)
|
||||
return false;
|
||||
@@ -58,43 +60,65 @@ class User
|
||||
if (empty($_SESSION['user']))
|
||||
return false;
|
||||
|
||||
// timed out...
|
||||
if (!empty($_SESSION['timeout']) && $_SESSION['timeout'] <= time())
|
||||
return false;
|
||||
|
||||
$uData = DB::Aowow()->SelectRow(
|
||||
'SELECT a.`id`, a.`passHash`, a.`username`, a.`locale`, a.`userGroups`, a.`userPerms`, a.`allowExpire`, BIT_OR(ab.`typeMask`) AS "bans", IFNULL(SUM(r.`amount`), 0) AS "reputation", a.`dailyVotes`, a.`excludeGroups`
|
||||
$session = DB::Aowow()->selectRow('SELECT `userId`, `expires` FROM ?_account_sessions WHERE `status` = ?d AND `sessionId` = ?', SESSION_ACTIVE, session_id());
|
||||
$userData = DB::Aowow()->selectRow(
|
||||
'SELECT a.`id`, a.`passHash`, a.`username`, a.`locale`, a.`userGroups`, a.`userPerms`, BIT_OR(ab.`typeMask`) AS "bans", IFNULL(SUM(r.`amount`), 0) AS "reputation", a.`dailyVotes`, a.`excludeGroups`, a.`status`, a.`statusTimer`, a.`email`
|
||||
FROM ?_account a
|
||||
LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP()
|
||||
LEFT JOIN ?_account_reputation r ON a.`id` = r.`userId`
|
||||
LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP()
|
||||
LEFT JOIN ?_account_reputation r ON a.`id` = r.`userId`
|
||||
WHERE a.`id` = ?d
|
||||
GROUP BY a.`id`',
|
||||
$_SESSION['user']
|
||||
);
|
||||
|
||||
if (!$uData)
|
||||
return false;
|
||||
|
||||
if ($loc = Locale::tryFrom($uData['locale']))
|
||||
self::$preferedLoc = $loc;
|
||||
|
||||
// password changed, terminate session
|
||||
if (AUTH_MODE_SELF && $uData['passHash'] != $_SESSION['hash'])
|
||||
if (!$session || !$userData)
|
||||
{
|
||||
self::destroy();
|
||||
return false;
|
||||
}
|
||||
else if ($session['expires'] && $session['expires'] < time())
|
||||
{
|
||||
DB::Aowow()->query('UPDATE ?_account_sessions SET `touched` = ?d, `status` = ?d WHERE `sessionId` = ?', time(), SESSION_EXPIRED, session_id());
|
||||
self::destroy();
|
||||
return false;
|
||||
}
|
||||
else if ($session['userId'] != $userData['id']) // what in the name of fuck..?
|
||||
{
|
||||
// Don't know why, don't know how .. doesn't matter, both parties are out.
|
||||
DB::Aowow()->query('UPDATE ?_account_sessions SET `touched` = ?d, `status` = ?d WHERE `userId` IN (?a) AND `status` = ?d', time(), SESSION_FORCED_LOGOUT, [$userData['id'], $session['userId']], SESSION_ACTIVE);
|
||||
trigger_error('User::init - tried to resume session "'.session_id().'" of user #'.$_SESSION['user'].' linked to session data for user #'.$session['userId'].' Kicked both!', E_USER_ERROR);
|
||||
self::destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$id = intVal($uData['id']);
|
||||
self::$username = $uData['username'];
|
||||
self::$passHash = $uData['passHash'];
|
||||
self::$expires = (bool)$uData['allowExpire'];
|
||||
self::$reputation = $uData['reputation'];
|
||||
self::$banStatus = $uData['bans'];
|
||||
self::$groups = self::isBanned() ? 0 : intval($uData['userGroups']);
|
||||
self::$perms = self::isBanned() ? 0 : intval($uData['userPerms']);
|
||||
self::$dailyVotes = $uData['dailyVotes'];
|
||||
self::$excludeGroups = $uData['excludeGroups'];
|
||||
DB::Aowow()->query('UPDATE ?_account_sessions SET `touched` = ?d, `expires` = IF(`expires`, ?d, 0) WHERE `sessionId` = ?', time(), time() + Cfg::get('SESSION_TIMEOUT_DELAY'), session_id());
|
||||
|
||||
if ($loc = Locale::tryFrom($userData['locale']))
|
||||
self::$preferedLoc = $loc;
|
||||
|
||||
// reset expired account statuses
|
||||
if ($userData['statusTimer'] < time() && $userData['status'] > ACC_STATUS_NEW)
|
||||
{
|
||||
DB::Aowow()->query('UPDATE ?_account SET `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "" WHERE `id` = ?d', ACC_STATUS_OK, User::$id);
|
||||
$userData['status'] = ACC_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************/
|
||||
/* past here we are logged in */
|
||||
/*******************************/
|
||||
|
||||
self::$id = intVal($userData['id']);
|
||||
self::$username = $userData['username'];
|
||||
self::$reputation = $userData['reputation'];
|
||||
self::$banStatus = $userData['bans'];
|
||||
self::$groups = self::isBanned() ? 0 : intval($userData['userGroups']);
|
||||
self::$perms = self::isBanned() ? 0 : intval($userData['userPerms']);
|
||||
self::$dailyVotes = $userData['dailyVotes'];
|
||||
self::$excludeGroups = $userData['excludeGroups'];
|
||||
self::$status = $userData['status'];
|
||||
// self::$debug = $userData['debug']; // TBD
|
||||
self::$email = $userData['email'];
|
||||
|
||||
$conditions = [['OR', ['user', self::$id], ['ap.accountId', self::$id]]];
|
||||
if (!self::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||
@@ -104,10 +128,10 @@ class User
|
||||
|
||||
|
||||
// stuff, that updates on a daily basis goes here (if you keep you session alive indefinitly, the signin-handler doesn't do very much)
|
||||
// - conscutive visits
|
||||
// - consecutive visits
|
||||
// - votes per day
|
||||
// - reputation for daily visit
|
||||
if (self::isLoggedIn())
|
||||
if (!self::isBanned())
|
||||
{
|
||||
$lastLogin = DB::Aowow()->selectCell('SELECT `curLogin` FROM ?_account WHERE `id` = ?d', self::$id);
|
||||
// either the day changed or the last visit was >24h ago
|
||||
@@ -130,7 +154,7 @@ class User
|
||||
Util::gainSiteReputation(self::$id, SITEREP_ACTION_DAILYVISIT);
|
||||
|
||||
// increment consecutive visits (next day or first of new month and not more than 48h)
|
||||
// i bet my ass i forgott a corner case
|
||||
// i bet my ass i forgot a corner case
|
||||
if ((date('j', $lastLogin) + 1 == date('j') || (date('j') == 1 && date('n', $lastLogin) != date('n'))) && (time() - $lastLogin) < 2 * DAY)
|
||||
DB::Aowow()->query('UPDATE ?_account SET `consecutiveVisits` = `consecutiveVisits` + 1 WHERE `id` = ?d', self::$id);
|
||||
else
|
||||
@@ -169,9 +193,7 @@ class User
|
||||
public static function save(bool $toDB = false)
|
||||
{
|
||||
$_SESSION['user'] = self::$id;
|
||||
$_SESSION['hash'] = self::$passHash;
|
||||
$_SESSION['locale'] = self::$preferedLoc;
|
||||
$_SESSION['timeout'] = self::$expires ? time() + Cfg::get('SESSION_TIMEOUT_DELAY') : 0;
|
||||
// $_SESSION['dataKey'] does not depend on user login status and is set in User::init()
|
||||
|
||||
if (self::isLoggedIn() && $toDB)
|
||||
@@ -200,27 +222,27 @@ class User
|
||||
public static function authenticate(string $login, string $password) : int
|
||||
{
|
||||
$userId = 0;
|
||||
$hash = '';
|
||||
|
||||
$result = match (Cfg::get('ACC_AUTH_MODE'))
|
||||
{
|
||||
AUTH_MODE_SELF => self::authSelf($login, $password, $userId, $hash),
|
||||
AUTH_MODE_REALM => self::authRealm($login, $password, $userId, $hash),
|
||||
AUTH_MODE_EXTERNAL => self::authExtern($login, $password, $userId, $hash),
|
||||
AUTH_MODE_SELF => self::authSelf($login, $password, $userId),
|
||||
AUTH_MODE_REALM => self::authRealm($login, $password, $userId),
|
||||
AUTH_MODE_EXTERNAL => self::authExtern($login, $password, $userId),
|
||||
default => AUTH_INTERNAL_ERR
|
||||
};
|
||||
|
||||
if ($result == AUTH_OK)
|
||||
// also banned? its a feature block, not login block..
|
||||
if ($result == AUTH_OK || $result == AUTH_BANNED)
|
||||
{
|
||||
session_unset();
|
||||
$_SESSION['user'] = $userId;
|
||||
$_SESSION['hash'] = self::hashCrypt($hash);
|
||||
self::$id = $userId;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private static function authSelf(string $nameOrEmail, string $password, int &$userId, string &$hash) : int
|
||||
private static function authSelf(string $nameOrEmail, string $password, int &$userId) : int
|
||||
{
|
||||
if (!self::$ip)
|
||||
return AUTH_INTERNAL_ERR;
|
||||
@@ -250,8 +272,7 @@ class User
|
||||
if (!$query)
|
||||
return AUTH_WRONGUSER;
|
||||
|
||||
self::$passHash = $query['passHash'];
|
||||
if (!self::verifyCrypt($password))
|
||||
if (!self::verifyCrypt($password, $query['passHash']))
|
||||
return AUTH_WRONGPASS;
|
||||
|
||||
// successfull auth; clear bans for this IP
|
||||
@@ -261,12 +282,11 @@ class User
|
||||
return AUTH_BANNED;
|
||||
|
||||
$userId = $query['id'];
|
||||
$hash = $query['passHash'];
|
||||
|
||||
return AUTH_OK;
|
||||
}
|
||||
|
||||
private static function authRealm(string $name, string $password, int &$userId, string &$hash) : int
|
||||
private static function authRealm(string $name, string $password, int &$userId) : int
|
||||
{
|
||||
if (!DB::isConnectable(DB_AUTH))
|
||||
return AUTH_INTERNAL_ERR;
|
||||
@@ -289,7 +309,7 @@ class User
|
||||
return AUTH_OK;
|
||||
}
|
||||
|
||||
private static function authExtern(string $nameOrEmail, string $password, int &$userId, string &$hash) : int
|
||||
private static function authExtern(string $nameOrEmail, string $password, int &$userId) : int
|
||||
{
|
||||
if (!file_exists('config/extAuth.php'))
|
||||
{
|
||||
@@ -334,7 +354,7 @@ class User
|
||||
return $_;
|
||||
}
|
||||
|
||||
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (`extId`, `login`, `passHash`, `username`, `email`, `joinDate`, `allowExpire`, `prevIP`, `prevLogin`, `locale`, `status`, `userGroups`) VALUES (?d, "", "", ?, "", UNIX_TIMESTAMP(), 0, ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)',
|
||||
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (`extId`, `passHash`, `username`, `joinDate`, `prevIP`, `prevLogin`, `locale`, `status`, `userGroups`) VALUES (?d, "", ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)',
|
||||
$extId,
|
||||
$name,
|
||||
$_SERVER["REMOTE_ADDR"] ?? '',
|
||||
@@ -364,12 +384,12 @@ class User
|
||||
return crypt($pass, self::createSalt());
|
||||
}
|
||||
|
||||
public static function verifyCrypt(string $pass, string $hash = '') : string
|
||||
public static function verifyCrypt(string $pass, string $hash) : bool
|
||||
{
|
||||
$_ = $hash ?: self::$passHash;
|
||||
return $_ === crypt($pass, $_);
|
||||
return $hash === crypt($pass, $hash);
|
||||
}
|
||||
|
||||
// SRP6 used by TC
|
||||
private static function verifySRP6(string $user, string $pass, string $salt, string $verifier) : bool
|
||||
{
|
||||
$g = gmp_init(7);
|
||||
@@ -409,7 +429,7 @@ class User
|
||||
return $errCode == 0;
|
||||
}
|
||||
|
||||
public static function isValidPass(string $pass, int &$errCode = 0) : bool
|
||||
public static function isValidPass(string $pass, ?int &$errCode = 0) : bool
|
||||
{
|
||||
$errCode = 0;
|
||||
|
||||
@@ -511,6 +531,11 @@ class User
|
||||
return self::$banStatus & (ACC_BAN_TEMP | ACC_BAN_PERM | $addBanMask);
|
||||
}
|
||||
|
||||
public static function isRecovering() : bool
|
||||
{
|
||||
return self::$status == ACC_STATUS_RECOVER_USER || self::$status == ACC_STATUS_RECOVER_PASS;
|
||||
}
|
||||
|
||||
|
||||
/**************/
|
||||
/* js-related */
|
||||
@@ -553,7 +578,7 @@ class User
|
||||
return self::$reputation;
|
||||
}
|
||||
|
||||
public static function getUserGlobals() : array
|
||||
public static function getUserGlobal() : array
|
||||
{
|
||||
$gUser = array(
|
||||
'id' => self::$id,
|
||||
@@ -577,7 +602,15 @@ class User
|
||||
$gUser['excludegroups'] = self::$excludeGroups;
|
||||
|
||||
if (Cfg::get('DEBUG') && User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN | U_GROUP_TESTER))
|
||||
$gUser['debug'] = true; // csv id-list output option on listviews; todo - set on per user basis
|
||||
$gUser['debug'] = true; // csv id-list output option on listviews
|
||||
|
||||
if (self::getPremiumBorder())
|
||||
$gUser['settings'] = ['premiumborder' => 1];
|
||||
else
|
||||
$gUser['settings'] = (new \StdClass); // existence is checked in Profiler.js before g_user.excludegroups is applied
|
||||
|
||||
if (self::isPremium())
|
||||
$gUser['premium'] = 1;
|
||||
|
||||
if (self::getPremiumBorder())
|
||||
$gUser['settings'] = ['premiumborder' => 1];
|
||||
|
||||
@@ -137,10 +137,7 @@ class AccountPage extends GenericPage
|
||||
if ($err = $this->doSignIn())
|
||||
$this->error = $err;
|
||||
else
|
||||
{
|
||||
session_regenerate_id(true); // user status changed => regenerate id
|
||||
header('Location: '.$this->getNext(true), true, 302);
|
||||
}
|
||||
}
|
||||
else if ($this->_get['token'] && ($_ = DB::Aowow()->selectCell('SELECT `username` FROM ?_account WHERE `status` IN (?a) AND `token` = ? AND `statusTimer` > UNIX_TIMESTAMP()', [ACC_STATUS_RECOVER_USER, ACC_STATUS_OK], $this->_get['token'])))
|
||||
$this->user = $_;
|
||||
@@ -184,6 +181,8 @@ class AccountPage extends GenericPage
|
||||
$this->head = sprintf(Lang::account('register'), $nStep);
|
||||
break;
|
||||
case 'signout':
|
||||
DB::Aowow()->query('UPDATE ?_account_sessions SET `touched` = ?d, `status` = ?d WHERE `sessionId` = ?', time(), SESSION_LOGOUT, session_id());
|
||||
|
||||
User::destroy();
|
||||
default:
|
||||
header('Location: '.$this->getNext(true), true, 302);
|
||||
@@ -365,15 +364,20 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
return Lang::main('intError');
|
||||
|
||||
// reset account status, update expiration
|
||||
DB::Aowow()->query('UPDATE ?_account SET `prevIP` = IF(`curIp` = ?, `prevIP`, `curIP`), `curIP` = IF(`curIp` = ?, `curIP`, ?), `allowExpire` = ?d, `status` = IF(`status` = ?d, `status`, 0), `statusTimer` = IF(`status` = ?d, `statusTimer`, 0), `token` = IF(`status` = ?d, `token`, "") WHERE LOWER(`username`) = LOWER(?)',
|
||||
DB::Aowow()->query('UPDATE ?_account SET `prevIP` = IF(`curIp` = ?, `prevIP`, `curIP`), `curIP` = IF(`curIp` = ?, `curIP`, ?), `status` = IF(`status` = ?d, `status`, 0), `statusTimer` = IF(`status` = ?d, `statusTimer`, 0), `token` = IF(`status` = ?d, `token`, "") WHERE LOWER(`username`) = LOWER(?)',
|
||||
User::$ip, User::$ip, User::$ip,
|
||||
$this->_post['remember_me'] != 'yes',
|
||||
ACC_STATUS_NEW, ACC_STATUS_NEW, ACC_STATUS_NEW,
|
||||
$this->_post['username']
|
||||
);
|
||||
|
||||
if (User::init())
|
||||
User::save(); // overwrites the current user
|
||||
session_regenerate_id(true); // user status changed => regenerate id
|
||||
|
||||
// create new session entry
|
||||
DB::Aowow()->query('INSERT INTO ?_account_sessions (`userId`, `sessionId`, `created`, `expires`, `touched`, `deviceInfo`, `ip`, `status`) VALUES (?d, ?, ?d, ?d, ?d, ?, ?, ?d)',
|
||||
User::$id, session_id(), time(), $this->_post['remember_me'] ? 0 : time() + Cfg::get('SESSION_TIMEOUT_DELAY'), time(), User::$agent, User::$ip, SESSION_ACTIVE);
|
||||
|
||||
if (User::init()) // reinitialize the user
|
||||
User::save();
|
||||
|
||||
return;
|
||||
case AUTH_BANNED:
|
||||
@@ -432,13 +436,12 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
|
||||
// create..
|
||||
$token = Util::createHash();
|
||||
$ok = DB::Aowow()->query('REPLACE INTO ?_account (`login`, `passHash`, `username`, `email`, `joindate`, `curIP`, `allowExpire`, `locale`, `userGroups`, `status`, `statusTimer`, `token`) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), ?, ?d, ?d, ?d, ?d, UNIX_TIMESTAMP() + ?d, ?)',
|
||||
$ok = DB::Aowow()->query('REPLACE INTO ?_account (`login`, `passHash`, `username`, `email`, `joindate`, `curIP`, `locale`, `userGroups`, `status`, `statusTimer`, `token`) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), ?, ?d, ?d, ?d, ?d, UNIX_TIMESTAMP() + ?d, ?)',
|
||||
$this->_post['username'],
|
||||
User::hashCrypt($this->_post['password']),
|
||||
$this->_post['username'],
|
||||
$this->_post['email'],
|
||||
User::$ip,
|
||||
$this->_post['remember_me'] != 'yes',
|
||||
Lang::getLocale()->value,
|
||||
U_GROUP_PENDING,
|
||||
ACC_STATUS_NEW,
|
||||
@@ -479,18 +482,18 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
if (!Util::isValidEmail($this->_post['email']))
|
||||
return Lang::account('emailInvalid');
|
||||
|
||||
$uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE token = ? AND email = ? AND status = ?d AND statusTimer > UNIX_TIMESTAMP()',
|
||||
$userData = DB::Aowow()->selectRow('SELECT `id, `passHash` FROM ?_account WHERE `token` = ? AND `email` = ? AND `status` = ?d AND `statusTimer` > UNIX_TIMESTAMP()',
|
||||
$this->_post['token'],
|
||||
$this->_post['email'],
|
||||
ACC_STATUS_RECOVER_PASS
|
||||
);
|
||||
if (!$uId)
|
||||
if (!$userData)
|
||||
return Lang::account('emailNotFound'); // assume they didn't meddle with the token
|
||||
|
||||
if (!User::verifyCrypt($this->_post['c_password']))
|
||||
if (!User::verifyCrypt($this->_post['c_password'], $userData['passHash']))
|
||||
return Lang::account('newPassDiff');
|
||||
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET passHash = ?, status = ?d WHERE id = ?d', User::hashCrypt($this->_post['c_password']), ACC_STATUS_OK, $uId))
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET `passHash` = ?, `status` = ?d WHERE `id` = ?d', User::hashCrypt($this->_post['c_password']), ACC_STATUS_OK, $userData['id']))
|
||||
return Lang::main('intError');
|
||||
}
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ class GenericPage
|
||||
if ($ahl = DB::Aowow()->selectCell('SELECT altHeaderLogo FROM ?_home_featuredbox WHERE ?d BETWEEN startDate AND endDate ORDER BY id DESC', time()))
|
||||
$this->headerLogo = Util::defStatic($ahl);
|
||||
|
||||
$this->gUser = User::getUserGlobals();
|
||||
$this->gUser = User::getUserGlobal();
|
||||
$this->gFavorites = User::getFavorites();
|
||||
$this->pageTemplate['pageName'] = strtolower($pageCall);
|
||||
|
||||
|
||||
@@ -30,14 +30,13 @@ CREATE TABLE `aowow_account` (
|
||||
`username` varchar(64) NOT NULL COMMENT 'unique; used for for links and display',
|
||||
`email` varchar(64) DEFAULT NULL COMMENT 'unique; can be used for login if AUTH_SELF and can be NULL if not',
|
||||
`joinDate` int unsigned NOT NULL COMMENT 'unixtime',
|
||||
`allowExpire` tinyint unsigned NOT NULL,
|
||||
`dailyVotes` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`consecutiveVisits` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`curIP` varchar(45) NOT NULL DEFAULT '',
|
||||
`prevIP` varchar(45) NOT NULL DEFAULT '',
|
||||
`curLogin` int unsigned NOT NULL DEFAULT 0 COMMENT 'unixtime',
|
||||
`prevLogin` int unsigned NOT NULL DEFAULT 0,
|
||||
`locale` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '0,2,3,6,8',
|
||||
`locale` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '0,2,3,4,6,8',
|
||||
`userGroups` smallint unsigned NOT NULL DEFAULT 0 COMMENT 'bitmask',
|
||||
`avatar` varchar(50) NOT NULL DEFAULT '' COMMENT 'icon-string for internal or id for upload',
|
||||
`title` varchar(50) NOT NULL DEFAULT '' COMMENT 'user can obtain custom titles',
|
||||
@@ -181,6 +180,25 @@ CREATE TABLE `aowow_account_reputation` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPACT COMMENT='reputation log';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `aowow_account_sessions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `aowow_account_sessions`;
|
||||
CREATE TABLE `aowow_account_sessions` (
|
||||
`userId` int unsigned NOT NULL,
|
||||
`sessionId` varchar(190) NOT NULL COMMENT 'PHPSESSID',
|
||||
`created` int unsigned NOT NULL,
|
||||
`expires` int unsigned NOT NULL COMMENT 'timestamp or 0 (never expires)',
|
||||
`touched` int unsigned NOT NULL COMMENT 'timestamp - last used',
|
||||
`deviceInfo` varchar(256) NOT NULL,
|
||||
`ip` varchar(45) NOT NULL COMMENT 'can change; just last used ip',
|
||||
`status` enum('ACTIVE', 'LOGOUT', 'FORCEDLOGOUT', 'EXPIRED') NOT NULL,
|
||||
UNIQUE KEY `sessionId` (`sessionId`) USING BTREE,
|
||||
KEY `userId` (`userId`) USING BTREE,
|
||||
CONSTRAINT `FK_acc_sessions` FOREIGN KEY (`userId`) REFERENCES `aowow_account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPACT;
|
||||
|
||||
--
|
||||
-- Table structure for table `aowow_account_weightscale_data`
|
||||
--
|
||||
@@ -3323,7 +3341,7 @@ UNLOCK TABLES;
|
||||
|
||||
LOCK TABLES `aowow_dbversion` WRITE;
|
||||
/*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */;
|
||||
INSERT INTO `aowow_dbversion` VALUES (1753572320,0,NULL,NULL);
|
||||
INSERT INTO `aowow_dbversion` VALUES (1753574970,0,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ CLISetup::registerUtility(new class extends UtilityScript
|
||||
if (!$name || !$passw)
|
||||
return false;
|
||||
|
||||
if (DB::Aowow()->query('REPLACE INTO ?_account (`login`, `passHash`, `username`, `joindate`, `email`, `allowExpire`, `userGroups`, `userPerms`) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, 0, ?d, 1)',
|
||||
if (DB::Aowow()->query('REPLACE INTO ?_account (`login`, `passHash`, `username`, `joindate`, `email`, `userGroups`, `userPerms`) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, ?d, 1)',
|
||||
$name, User::hashCrypt($passw), $name, $email ?: Cfg::get('CONTACT_EMAIL'), U_GROUP_ADMIN))
|
||||
{
|
||||
$newId = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `username` = ?', $name);
|
||||
|
||||
@@ -3,6 +3,8 @@ ALTER TABLE `aowow_account`
|
||||
CHANGE COLUMN `user` `login` varchar(64) NOT NULL DEFAULT '' COMMENT 'only used for login',
|
||||
CHANGE COLUMN `displayName` `username` varchar(64) NOT NULL COMMENT 'unique; used for for links and display',
|
||||
MODIFY COLUMN `email` varchar(64) DEFAULT NULL COMMENT 'unique; can be used for login if AUTH_SELF and can be NULL if not',
|
||||
MODIFY COLUMN `token` varchar(40) DEFAULT NULL COMMENT 'identification key for changes to account',
|
||||
ADD COLUMN `updateValue` varchar(128) DEFAULT NULL COMMENT 'temp store for new passHash / email' AFTER `token`,
|
||||
ADD CONSTRAINT `username` UNIQUE (`username`);
|
||||
|
||||
UPDATE `aowow_account`
|
||||
|
||||
17
setup/updates/1753574969_01.sql
Normal file
17
setup/updates/1753574969_01.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
DROP TABLE IF EXISTS `aowow_account_sessions`;
|
||||
CREATE TABLE `aowow_account_sessions` (
|
||||
`userId` int unsigned NOT NULL,
|
||||
`sessionId` varchar(190) NOT NULL COMMENT 'PHPSESSID', -- max size (for utf8mb4) to still be a key
|
||||
`created` int unsigned NOT NULL,
|
||||
`expires` int unsigned NOT NULL COMMENT 'timestamp or 0 (never expires)',
|
||||
`touched` int unsigned NOT NULL COMMENT 'timestamp - last used',
|
||||
`deviceInfo` varchar(256) NOT NULL,
|
||||
`ip` varchar(45) NOT NULL COMMENT 'can change; just last used ip', -- think mobile switching between WLAN and mobile data
|
||||
`status` enum('ACTIVE', 'LOGOUT', 'FORCEDLOGOUT', 'EXPIRED') NOT NULL,
|
||||
UNIQUE KEY `sessionId` (`sessionId`) USING BTREE,
|
||||
KEY `userId` (`userId`) USING BTREE,
|
||||
CONSTRAINT `FK_acc_sessions` FOREIGN KEY (`userId`) REFERENCES `aowow_account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPACT;
|
||||
|
||||
ALTER TABLE `aowow_account`
|
||||
DROP COLUMN `allowExpire`;
|
||||
Reference in New Issue
Block a user