User/Misc

* don't run querys if not strictly required (e.g. query for chars from ajax context)
 * prepare user globals and favorites so errors can be handled and don't destroy the template
   this also allows for profiling of the affected queries
 * add keys to items table to speed up querying for recipes in general and user completions in particular
This commit is contained in:
Sarjuuk
2025-11-05 15:28:57 +01:00
parent 9020e36db6
commit 16c5b73cd3
6 changed files with 78 additions and 55 deletions

View File

@@ -30,6 +30,8 @@ class PageTemplate
private string $gStaticUrl;
private string $gHost;
private string $gServerTime;
private string $gUser;
private string $gFavorites;
private ?string $analyticsTag = null;
private bool $consentFooter = false;
private string $dbProfiles = '';
@@ -484,6 +486,9 @@ class PageTemplate
// js + css
$this->prepareScripts();
$this->gUser = Util::toJSON(User::getUserGlobal());
$this->gFavorites = Util::toJSON(User::getFavorites());
// db profiling
if (Cfg::get('DEBUG') >= LOG_LEVEL_INFO && User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
$this->dbProfiles = \Aowow\DB::getProfiles();

View File

@@ -29,7 +29,28 @@ class User
public static function init()
{
self::setIP();
# set ip #
$ipAddr = '';
foreach (['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'] as $env)
{
if ($rawIp = getenv($env))
{
if ($env == 'HTTP_X_FORWARDED')
$rawIp = explode(',', $rawIp)[0]; // [ip, proxy1, proxy2]
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
break;
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
break;
}
}
self::$ip = $ipAddr ?: null;
# set locale #
if (isset($_SESSION['locale']) && $_SESSION['locale'] instanceof Locale)
self::$preferedLoc = $_SESSION['locale']->validate() ?? Locale::getFallback();
@@ -38,8 +59,10 @@ class User
else
self::$preferedLoc = Locale::getFallback();
// session have a dataKey to access the JScripts (yes, also the anons)
if (empty($_SESSION['dataKey']))
# set basic data #
if (empty($_SESSION['dataKey'])) // session have a dataKey to access the JScripts (yes, also the anons)
$_SESSION['dataKey'] = Util::createHash(); // just some random numbers for identification purpose
self::$dataKey = $_SESSION['dataKey'];
@@ -48,7 +71,9 @@ class User
if (!self::$ip)
return false;
// check IP bans
# check IP bans #
if ($ipBan = DB::Aowow()->selectRow('SELECT `count`, IF(`unbanDate` > UNIX_TIMESTAMP(), 1, 0) AS "active" FROM ?_account_bannedips WHERE `ip` = ? AND `type` = ?d', self::$ip, IP_BAN_TYPE_LOGIN_ATTEMPT))
{
if ($ipBan['count'] > Cfg::get('ACC_FAILED_AUTH_COUNT') && $ipBan['active'])
@@ -57,7 +82,9 @@ class User
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE `ip` = ?', self::$ip);
}
// try to restore session
# try to restore session #
if (empty($_SESSION['user']))
return false;
@@ -122,16 +149,9 @@ class User
self::$email = $userData['email'];
self::$avatarborder = $userData['avatarborder'];
if (Cfg::get('PROFILER_ENABLE'))
{
$conditions = [['OR', ['user', self::$id], ['ap.accountId', self::$id]]];
if (!self::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
$conditions[] = [['cuFlags', PROFILER_CU_DELETED, '&'], 0];
self::$profiles = (new LocalProfileList($conditions));
}
# reset premium options #
// reset premium options
if (!self::isPremium())
{
if ($userData['avatar'] == 2)
@@ -144,17 +164,16 @@ class User
// do not reset, it's just not sent to the browser
}
// stuff, that updates on a daily basis goes here (if you keep you session alive indefinitly, the signin-handler doesn't do very much)
// - consecutive visits
// - votes per day
// - reputation for daily visit
# update daily limits #
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
if (date('j', $lastLogin) != date('j') || (time() - $lastLogin) > 1 * DAY)
{
// daily votes (we need to reset this one)
// - daily votes (we need to reset this one)
self::$dailyVotes = self::getMaxDailyVotes();
DB::Aowow()->query(
@@ -166,12 +185,11 @@ class User
self::$id
);
// gain rep for daily visit
// - gain reputation for daily visit
if (!(self::isBanned()) && !self::isInGroup(U_GROUP_PENDING))
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 forgot a corner case
// - increment consecutive visits (next day or first of new month and not more than 48h)
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
@@ -182,31 +200,6 @@ class User
return true;
}
private static function setIP() : void
{
$ipAddr = '';
$method = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'];
foreach ($method as $m)
{
if ($rawIp = getenv($m))
{
if ($m == 'HTTP_X_FORWARDED')
$rawIp = explode(',', $rawIp)[0]; // [ip, proxy1, proxy2]
// check IPv4
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
break;
// check IPv6
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
break;
}
}
self::$ip = $ipAddr ?: null;
}
public static function save(bool $toDB = false)
{
$_SESSION['user'] = self::$id;
@@ -640,7 +633,7 @@ class User
public static function getCharacters() : array
{
if (!self::$profiles)
if (!self::loadProfiles())
return [];
return self::$profiles->getJSGlobals(PROFILEINFO_CHARACTER);
@@ -648,7 +641,7 @@ class User
public static function getProfiles() : array
{
if (!self::$profiles)
if (!self::loadProfiles())
return [];
return self::$profiles->getJSGlobals(PROFILEINFO_PROFILE);
@@ -656,7 +649,7 @@ class User
public static function getPinnedCharacter() : array
{
if (!self::$profiles)
if (!self::loadProfiles())
return [];
$realms = Profiler::getRealms();
@@ -727,6 +720,9 @@ class User
public static function getCompletion() : array
{
if (!self::loadProfiles())
return [];
$ids = [];
foreach (self::$profiles->iterate() as $_)
if (!self::$profiles->isCustom())
@@ -752,7 +748,7 @@ class User
'SELECT pcs.`id` AS ARRAY_KEY, pcs.`spellId` AS ARRAY_KEY2, pcs.`spellId`, i.`id` AS "itemId"
FROM ?_spell s
JOIN ?_profiler_completion_spells pcs ON s.`id` = pcs.`spellId`
LEFT JOIN ?_items i ON i.spellId1 IN (?a) AND i.spellId2 = pcs.spellId
LEFT JOIN ?_items i ON i.`spellId1` IN (?a) AND i.`spellId2` = pcs.`spellId`
WHERE s.`typeCat` IN (?a) AND pcs.`id` IN (?a)',
LEARN_SPELLS, [-5, -6, 9, 11], $ids
);
@@ -776,6 +772,23 @@ class User
return $completion;
}
private static function loadProfiles() : bool
{
if (!Cfg::get('PROFILER_ENABLE'))
return false;
if (self::$profiles === null)
{
$conditions = [['OR', ['user', self::$id], ['ap.accountId', self::$id]]];
if (!self::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
$conditions[] = [['cuFlags', PROFILER_CU_DELETED, '&'], 0];
self::$profiles = (new LocalProfileList($conditions));
}
return !!self::$profiles->getFoundIDs();
}
}
?>

View File

@@ -1441,7 +1441,9 @@ CREATE TABLE `aowow_items` (
KEY `items_index` (`class`),
KEY `idx_model` (`displayId`),
KEY `idx_faction` (`requiredFaction`),
KEY `iconId` (`iconId`)
KEY `iconId` (`iconId`),
KEY `spellId1` (`spellId1`),
KEY `spellId2` (`spellId2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

View File

@@ -71,7 +71,7 @@ UNLOCK TABLES;
LOCK TABLES `aowow_dbversion` WRITE;
/*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */;
INSERT INTO `aowow_dbversion` VALUES (1758578400,17,NULL,NULL);
INSERT INTO `aowow_dbversion` VALUES (1762352734,0,NULL,NULL);
/*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */;
UNLOCK TABLES;

View File

@@ -0,0 +1,3 @@
ALTER TABLE `aowow_items`
ADD KEY spellId1 (`spellId1`),
ADD KEY spellId2 (`spellId2`);

View File

@@ -22,10 +22,10 @@ endif;
</script>
<?=$this->renderArray('js', 4); ?>
<script type="text/javascript">
var g_user = <?=$this->json($this->user::getUserGlobal()); ?>;
var g_user = <?=$this->gUser; ?>;
<?php
if ($fav = $this->user::getFavorites()):
echo " g_favorites = ".$this->json($fav).";\n";
if ($this->gFavorites):
echo " g_favorites = ".$this->gFavorites.";\n";
endif;
?>
</script>