Added targeted permission recalculation.
Reduces reliance on full recalculation and actually makes it viable to do from within the browser.
This commit is contained in:
parent
f03c8ebfa5
commit
40558ceb39
5 changed files with 74 additions and 52 deletions
|
@ -101,7 +101,7 @@ while(!$restricted && !empty($register)) {
|
|||
|
||||
$users->addRoles($userInfo, $defaultRoleInfo);
|
||||
$config->setString('users.newest', $userInfo->getId());
|
||||
$config->setBoolean('perms.needsRecalc', true);
|
||||
$msz->getPerms()->precalculatePermissions($msz->getForum(), [$userInfo->getId()]);
|
||||
|
||||
url_redirect('auth-login-welcome', ['username' => $userInfo->getName()]);
|
||||
return;
|
||||
|
|
|
@ -132,6 +132,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
|
|||
foreach($permsApply as $categoryName => $values)
|
||||
$perms->setPermissions($categoryName, $values['allow'], $values['deny'], roleInfo: $roleInfo);
|
||||
|
||||
// could target all users with the role but ech
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ $canEditPerms = $canEdit && $canManagePerms;
|
|||
|
||||
$permsInfos = $perms->getPermissionInfo(userInfo: $userInfo, categoryNames: Perm::INFO_FOR_USER);
|
||||
$permsLists = Perm::createList(Perm::LISTS_FOR_USER);
|
||||
$permsNeedRecalc = false;
|
||||
|
||||
if(CSRF::validateRequest() && $canEdit) {
|
||||
if(!empty($_POST['impersonate_user'])) {
|
||||
|
@ -143,7 +144,7 @@ if(CSRF::validateRequest() && $canEdit) {
|
|||
$users->addRoles($userInfo, $addRoles);
|
||||
|
||||
if(!empty($addRoles) || !empty($removeRoles))
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
$permsNeedRecalc = true;
|
||||
}
|
||||
|
||||
if(!empty($_POST['user']) && is_array($_POST['user'])) {
|
||||
|
@ -214,9 +215,12 @@ if(CSRF::validateRequest() && $canEdit) {
|
|||
foreach($permsApply as $categoryName => $values)
|
||||
$perms->setPermissions($categoryName, $values['allow'], $values['deny'], userInfo: $userInfo);
|
||||
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
$permsNeedRecalc = true;
|
||||
}
|
||||
|
||||
if($permsNeedRecalc)
|
||||
$perms->precalculatePermissions($msz->getForum(), [$userInfo->getId()]);
|
||||
|
||||
url_redirect('manage-user', ['user' => $userInfo->getId()]);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ if(!$isRestricted && $isVerifiedRequest && !empty($_POST['role'])) {
|
|||
case 'leave':
|
||||
if($roleInfo->isLeavable()) {
|
||||
$users->removeRoles($userInfo, $roleInfo);
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
$msz->getPerms()->precalculatePermissions($msz->getForum(), [$userInfo->getId()]);
|
||||
} else
|
||||
$errors[] = "You're not allow to leave this role, an administrator has to remove it for you.";
|
||||
break;
|
||||
|
|
|
@ -225,35 +225,47 @@ class Permissions {
|
|||
return $sets;
|
||||
}
|
||||
|
||||
// precalculates all permissions for fast lookups, don't run this from the browser lol
|
||||
// TODO: only recalc a subset of users (e.g. personal permission changes/role add/remove)
|
||||
public function precalculatePermissions(Forum $forum): void {
|
||||
self::precalculatePermissionsLog('Loading list of user IDs...');
|
||||
$userIds = [];
|
||||
$result = $this->dbConn->query('SELECT user_id FROM msz_users');
|
||||
while($result->next())
|
||||
$userIds[] = $result->getString(0);
|
||||
// precalculates all permissions for fast lookups
|
||||
public function precalculatePermissions(Forum $forum, array $userIds = []): void {
|
||||
$suppliedUsers = !empty($userIds);
|
||||
$doGuest = !$suppliedUsers;
|
||||
|
||||
self::precalculatePermissionsLog('Clearing existing precalculations...');
|
||||
$this->dbConn->execute('TRUNCATE msz_perms_calculated');
|
||||
if($suppliedUsers) {
|
||||
self::precalculatePermissionsLog('Removing calculations for given user ids...');
|
||||
$stmt = $this->cache->get('DELETE FROM msz_perms_calculated WHERE user_id = ?');
|
||||
foreach($userIds as $userId) {
|
||||
$stmt->addParameter(1, $userId);
|
||||
$stmt->execute();
|
||||
}
|
||||
} else {
|
||||
self::precalculatePermissionsLog('Loading list of user IDs...');
|
||||
$result = $this->dbConn->query('SELECT user_id FROM msz_users');
|
||||
while($result->next())
|
||||
$userIds[] = $result->getString(0);
|
||||
|
||||
self::precalculatePermissionsLog('Clearing existing precalculations...');
|
||||
$this->dbConn->execute('TRUNCATE msz_perms_calculated');
|
||||
}
|
||||
|
||||
self::precalculatePermissionsLog('Creating inserter statement...');
|
||||
$insert = $this->cache->get('INSERT INTO msz_perms_calculated (user_id, forum_id, perms_category, perms_calculated) VALUES (?, ?, ?, ?)');
|
||||
|
||||
self::precalculatePermissionsLog('Calculating guest permissions...');
|
||||
$result = $this->dbConn->query('SELECT perms_category, BIT_OR(perms_allow) & ~BIT_OR(perms_deny) FROM msz_perms WHERE forum_id IS NULL AND user_id IS NULL AND role_id IS NULL GROUP BY perms_category');
|
||||
$insert->addParameter(1, null);
|
||||
$insert->addParameter(2, null);
|
||||
while($result->next()) {
|
||||
$category = $result->getString(0);
|
||||
$perms = $result->getInteger(1);
|
||||
if($perms === 0)
|
||||
continue;
|
||||
if($doGuest) {
|
||||
self::precalculatePermissionsLog('Calculating guest permissions...');
|
||||
$result = $this->dbConn->query('SELECT perms_category, BIT_OR(perms_allow) & ~BIT_OR(perms_deny) FROM msz_perms WHERE forum_id IS NULL AND user_id IS NULL AND role_id IS NULL GROUP BY perms_category');
|
||||
$insert->addParameter(1, null);
|
||||
$insert->addParameter(2, null);
|
||||
while($result->next()) {
|
||||
$category = $result->getString(0);
|
||||
$perms = $result->getInteger(1);
|
||||
if($perms === 0)
|
||||
continue;
|
||||
|
||||
self::precalculatePermissionsLog('Inserting guest permissions for category %s with value %x...', $category, $perms);
|
||||
$insert->addParameter(3, $category);
|
||||
$insert->addParameter(4, $perms);
|
||||
$insert->execute();
|
||||
self::precalculatePermissionsLog('Inserting guest permissions for category %s with value %x...', $category, $perms);
|
||||
$insert->addParameter(3, $category);
|
||||
$insert->addParameter(4, $perms);
|
||||
$insert->execute();
|
||||
}
|
||||
}
|
||||
|
||||
self::precalculatePermissionsLog('Calculating user permissions...');
|
||||
|
@ -285,39 +297,41 @@ class Permissions {
|
|||
self::precalculatePermissionsLog('Loading list of forum categories...');
|
||||
$forumCats = $forum->getCategories(asTree: true);
|
||||
foreach($forumCats as $forumCat)
|
||||
$this->precalculatePermissionsForForumCategory($insert, $userIds, $forumCat);
|
||||
$this->precalculatePermissionsForForumCategory($insert, $userIds, $forumCat, $doGuest);
|
||||
|
||||
self::precalculatePermissionsLog('Finished permission precalculations!');
|
||||
}
|
||||
|
||||
private function precalculatePermissionsForForumCategory(IDbStatement $insert, array $userIds, object $forumCat, array $catIds = []): void {
|
||||
private function precalculatePermissionsForForumCategory(IDbStatement $insert, array $userIds, object $forumCat, bool $doGuest, array $catIds = []): void {
|
||||
$catIds[] = $currentCatId = $forumCat->info->getId();
|
||||
self::precalculatePermissionsLog('Precalcuting permissions for forum category #%s (%s)...', $currentCatId, implode(' <- ', $catIds));
|
||||
|
||||
self::precalculatePermissionsLog('Calculating guest permission for forum category #%s...', $currentCatId);
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get(sprintf(
|
||||
'SELECT perms_category, BIT_OR(perms_allow) & ~BIT_OR(perms_deny) FROM msz_perms WHERE forum_id IN (%s) AND user_id IS NULL AND role_id IS NULL GROUP BY perms_category',
|
||||
DbTools::prepareListString($catIds)
|
||||
));
|
||||
foreach($catIds as $catId)
|
||||
$stmt->addParameter(++$args, $catId);
|
||||
$stmt->execute();
|
||||
if($doGuest) {
|
||||
self::precalculatePermissionsLog('Calculating guest permission for forum category #%s...', $currentCatId);
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get(sprintf(
|
||||
'SELECT perms_category, BIT_OR(perms_allow) & ~BIT_OR(perms_deny) FROM msz_perms WHERE forum_id IN (%s) AND user_id IS NULL AND role_id IS NULL GROUP BY perms_category',
|
||||
DbTools::prepareListString($catIds)
|
||||
));
|
||||
foreach($catIds as $catId)
|
||||
$stmt->addParameter(++$args, $catId);
|
||||
$stmt->execute();
|
||||
|
||||
$insert->reset();
|
||||
$insert->addParameter(1, null);
|
||||
$insert->addParameter(2, $currentCatId);
|
||||
$result = $stmt->getResult();
|
||||
while($result->next()) {
|
||||
$category = $result->getString(0);
|
||||
$perms = $result->getInteger(1);
|
||||
if($perms === 0)
|
||||
continue;
|
||||
$insert->reset();
|
||||
$insert->addParameter(1, null);
|
||||
$insert->addParameter(2, $currentCatId);
|
||||
$result = $stmt->getResult();
|
||||
while($result->next()) {
|
||||
$category = $result->getString(0);
|
||||
$perms = $result->getInteger(1);
|
||||
if($perms === 0)
|
||||
continue;
|
||||
|
||||
self::precalculatePermissionsLog('Inserting guest permissions for category %s with value %x for forum category #%s...', $category, $perms, $currentCatId);
|
||||
$insert->addParameter(3, $category);
|
||||
$insert->addParameter(4, $perms);
|
||||
$insert->execute();
|
||||
self::precalculatePermissionsLog('Inserting guest permissions for category %s with value %x for forum category #%s...', $category, $perms, $currentCatId);
|
||||
$insert->addParameter(3, $category);
|
||||
$insert->addParameter(4, $perms);
|
||||
$insert->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$args = 0;
|
||||
|
@ -352,10 +366,13 @@ class Permissions {
|
|||
}
|
||||
|
||||
foreach($forumCat->children as $forumChild)
|
||||
$this->precalculatePermissionsForForumCategory($insert, $userIds, $forumChild, $catIds);
|
||||
$this->precalculatePermissionsForForumCategory($insert, $userIds, $forumChild, $doGuest, $catIds);
|
||||
}
|
||||
|
||||
private static function precalculatePermissionsLog(string $fmt, ...$args): void {
|
||||
if(!MSZ_CLI)
|
||||
return;
|
||||
|
||||
echo DateTime::now()->format('[H:i:s.u] ');
|
||||
vprintf($fmt, $args);
|
||||
echo PHP_EOL;
|
||||
|
|
Loading…
Reference in a new issue