Rewrote permissions system.
This commit is contained in:
parent
0d90b6576b
commit
349cc237c5
63 changed files with 1286 additions and 989 deletions
README.md
database
misuzu.phppublic-legacy
public
src
Auth
Comments
MisuzuContext.phpPerm.phpPerms
IPermissionResult.phpPermissionInfo.phpPermissionResult.phpPermissionResultShared.phpPermissions.php
SharpChat
Users/Assets
perms.phptemplates
tools
|
@ -2,6 +2,6 @@
|
|||
> Misuzu can and will steal your lunch money.
|
||||
|
||||
## Requirements
|
||||
- PHP 8.2
|
||||
- PHP 8.2 (64-bit)
|
||||
- MariaDB 10.6
|
||||
- [Composer](https://getcomposer.org/)
|
||||
|
|
125
database/2023_08_30_213930_new_permissions_system.php
Normal file
125
database/2023_08_30_213930_new_permissions_system.php
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
use Index\Data\IDbConnection;
|
||||
use Index\Data\Migration\IDbMigration;
|
||||
|
||||
final class NewPermissionsSystem_20230830_213930 implements IDbMigration {
|
||||
public function migrate(IDbConnection $conn): void {
|
||||
// make sure cron doesn't fuck us over
|
||||
$conn->execute('DELETE FROM msz_config WHERE config_name = "perms.needsRecalc"');
|
||||
|
||||
$conn->execute('
|
||||
CREATE TABLE msz_perms (
|
||||
user_id INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
role_id INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
forum_id INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
perms_category VARBINARY(64) NOT NULL,
|
||||
perms_allow BIGINT(20) UNSIGNED NOT NULL,
|
||||
perms_deny BIGINT(20) UNSIGNED NOT NULL,
|
||||
UNIQUE KEY perms_unique (user_id, role_id, forum_id, perms_category),
|
||||
KEY perms_user_foreign (user_id),
|
||||
KEY perms_role_foreign (role_id),
|
||||
KEY perms_forum_foreign (forum_id),
|
||||
KEY perms_category_index (perms_category),
|
||||
CONSTRAINT perms_user_foreign
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES msz_users (user_id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT perms_role_foreign
|
||||
FOREIGN KEY (role_id)
|
||||
REFERENCES msz_roles (role_id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT perms_forum_foreign
|
||||
FOREIGN KEY (forum_id)
|
||||
REFERENCES msz_forum_categories (forum_id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB COLLATE=utf8mb4_bin
|
||||
');
|
||||
|
||||
$conn->execute('
|
||||
ALTER TABLE msz_perms
|
||||
ADD CONSTRAINT perms_53bit
|
||||
CHECK (perms_allow >= 0 AND perms_deny >= 0 AND perms_allow <= 9007199254740991 AND perms_deny <= 9007199254740991),
|
||||
ADD CONSTRAINT perms_only_user_or_role
|
||||
CHECK ((user_id IS NULL AND role_id IS NULL) OR (user_id IS NULL AND role_id IS NOT NULL) OR (user_id IS NOT NULL AND role_id IS NULL))
|
||||
');
|
||||
|
||||
$conn->execute('
|
||||
CREATE TABLE msz_perms_calculated (
|
||||
user_id INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
forum_id INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
perms_category VARBINARY(64) NOT NULL,
|
||||
perms_calculated BIGINT(20) UNSIGNED NOT NULL,
|
||||
UNIQUE KEY perms_calculated_unique (user_id, forum_id, perms_category),
|
||||
KEY perms_calculated_user_foreign (user_id),
|
||||
KEY perms_calculated_forum_foreign (forum_id),
|
||||
KEY perms_calculated_category_index (perms_category),
|
||||
CONSTRAINT perms_calculated_user_foreign
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES msz_users (user_id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT perms_calculated_forum_foreign
|
||||
FOREIGN KEY (forum_id)
|
||||
REFERENCES msz_forum_categories (forum_id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB COLLATE=utf8mb4_bin
|
||||
');
|
||||
|
||||
$conn->execute('
|
||||
ALTER TABLE msz_perms_calculated
|
||||
ADD CONSTRAINT perms_calculated_53bit
|
||||
CHECK (perms_calculated >= 0 AND perms_calculated <= 9007199254740991)
|
||||
');
|
||||
|
||||
$insert = $conn->prepare('INSERT INTO msz_perms (user_id, role_id, forum_id, perms_category, perms_allow, perms_deny) VALUES (?, ?, ?, ?, ?, ?)');
|
||||
|
||||
$result = $conn->query('SELECT user_id, role_id, general_perms_allow, general_perms_deny, user_perms_allow, user_perms_deny, changelog_perms_allow, changelog_perms_deny, news_perms_allow, news_perms_deny, forum_perms_allow, forum_perms_deny, comments_perms_allow, comments_perms_deny FROM msz_permissions');
|
||||
while($result->next()) {
|
||||
$insert->addParameter(1, $result->isNull(0) ? null : $result->getString(0));
|
||||
$insert->addParameter(2, $result->isNull(1) ? null : $result->getString(1));
|
||||
$insert->addParameter(3, null);
|
||||
$insert->addParameter(4, 'user');
|
||||
$insert->addParameter(5, $result->getInteger(4));
|
||||
$insert->addParameter(6, $result->getInteger(5));
|
||||
$insert->execute();
|
||||
|
||||
$allow = $result->getInteger(2);
|
||||
$allow |= $result->getInteger(6) << 8;
|
||||
$allow |= $result->getInteger(8) << 16;
|
||||
$allow |= $result->getInteger(10) << 24;
|
||||
$allow |= $result->getInteger(12) << 32;
|
||||
|
||||
$deny = $result->getInteger(3);
|
||||
$deny |= $result->getInteger(7) << 8;
|
||||
$deny |= $result->getInteger(9) << 16;
|
||||
$deny |= $result->getInteger(11) << 24;
|
||||
$deny |= $result->getInteger(13) << 32;
|
||||
|
||||
$insert->addParameter(4, 'global');
|
||||
$insert->addParameter(5, $allow);
|
||||
$insert->addParameter(6, $deny);
|
||||
$insert->execute();
|
||||
}
|
||||
|
||||
$result = $conn->query('SELECT user_id, role_id, forum_id, forum_perms_allow, forum_perms_deny FROM msz_forum_permissions');
|
||||
while($result->next()) {
|
||||
$insert->addParameter(1, $result->isNull(0) ? null : $result->getString(0));
|
||||
$insert->addParameter(2, $result->isNull(1) ? null : $result->getString(1));
|
||||
$insert->addParameter(3, $result->getString(2));
|
||||
$insert->addParameter(4, 'forum');
|
||||
$insert->addParameter(5, $result->getInteger(3));
|
||||
$insert->addParameter(6, $result->getInteger(4));
|
||||
$insert->execute();
|
||||
}
|
||||
|
||||
$conn->execute('DROP TABLE msz_forum_permissions');
|
||||
$conn->execute('DROP TABLE msz_permissions');
|
||||
|
||||
// schedule recalc
|
||||
$conn->execute('INSERT INTO msz_config (config_name, config_value) VALUES ("perms.needsRecalc", "b:1;")');
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@ mb_internal_encoding('utf-8');
|
|||
date_default_timezone_set('utc');
|
||||
|
||||
require_once MSZ_ROOT . '/utility.php';
|
||||
require_once MSZ_SOURCE . '/perms.php';
|
||||
require_once MSZ_SOURCE . '/url.php';
|
||||
|
||||
$dbConfig = parse_ini_file(MSZ_CONFIG . '/config.ini', true, INI_SCANNER_TYPED);
|
||||
|
|
|
@ -113,7 +113,7 @@ while(!empty($_POST['login']) && is_array($_POST['login'])) {
|
|||
if($userInfo->passwordNeedsRehash())
|
||||
$users->updateUser($userInfo, password: $_POST['login']['password']);
|
||||
|
||||
if(!empty($loginPermCat) && $loginPermVal > 0 && !perms_check_user($loginPermCat, $userInfo->getId(), $loginPermVal)) {
|
||||
if(!empty($loginPermCat) && $loginPermVal > 0 && !$msz->getPerms()->checkPermissions($loginPermCat, $loginPermVal, $userInfo)) {
|
||||
$notices[] = "Login succeeded, but you're not allowed to browse the site right now.";
|
||||
$loginAttempts->recordAttempt(true, $ipAddress, $countryCode, $userAgent, $clientInfo, $userInfo);
|
||||
break;
|
||||
|
|
|
@ -30,7 +30,7 @@ if($msz->hasActiveBan()) {
|
|||
$currentUserInfo = $msz->getActiveUser();
|
||||
|
||||
$comments = $msz->getComments();
|
||||
$commentPerms = perms_for_comments($currentUserInfo->getId());
|
||||
$perms = $msz->getAuthInfo()->getPerms('global');
|
||||
|
||||
$commentId = (string)filter_input(INPUT_GET, 'c', FILTER_SANITIZE_NUMBER_INT);
|
||||
$commentMode = (string)filter_input(INPUT_GET, 'm');
|
||||
|
@ -55,7 +55,7 @@ if($commentMode !== 'create' && empty($commentInfo)) {
|
|||
switch($commentMode) {
|
||||
case 'pin':
|
||||
case 'unpin':
|
||||
if(!$commentPerms['can_pin'] && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
if(!$perms->check(Perm::G_COMMENTS_PIN) && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
echo render_info("You're not allowed to pin comments.", 403);
|
||||
break;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ switch($commentMode) {
|
|||
break;
|
||||
|
||||
case 'vote':
|
||||
if(!$commentPerms['can_vote'] && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
if(!$perms->check(Perm::G_COMMENTS_VOTE) && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
echo render_info("You're not allowed to vote on comments.", 403);
|
||||
break;
|
||||
}
|
||||
|
@ -113,21 +113,23 @@ switch($commentMode) {
|
|||
break;
|
||||
|
||||
case 'delete':
|
||||
if(!$commentPerms['can_delete'] && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
$canDelete = $perms->check(Perm::G_COMMENTS_DELETE_OWN | Perm::G_COMMENTS_DELETE_ANY);
|
||||
if(!$canDelete && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
echo render_info("You're not allowed to delete comments.", 403);
|
||||
break;
|
||||
}
|
||||
|
||||
$canDeleteAny = $perms->check(Perm::G_COMMENTS_DELETE_ANY);
|
||||
if($commentInfo->isDeleted()) {
|
||||
echo render_info(
|
||||
$commentPerms['can_delete_any'] ? 'This comment is already marked for deletion.' : "This comment doesn't exist.",
|
||||
$canDeleteAny ? 'This comment is already marked for deletion.' : "This comment doesn't exist.",
|
||||
400
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
$isOwnComment = $commentInfo->getUserId() === $currentUserInfo->getId();
|
||||
$isModAction = $commentPerms['can_delete_any'] && !$isOwnComment;
|
||||
$isModAction = $canDeleteAny && !$isOwnComment;
|
||||
|
||||
if(!$isModAction && !$isOwnComment) {
|
||||
echo render_info("You're not allowed to delete comments made by others.", 403);
|
||||
|
@ -150,7 +152,7 @@ switch($commentMode) {
|
|||
break;
|
||||
|
||||
case 'restore':
|
||||
if(!$commentPerms['can_delete_any']) {
|
||||
if(!$perms->check(Perm::G_COMMENTS_DELETE_ANY)) {
|
||||
echo render_info("You're not allowed to restore deleted comments.", 403);
|
||||
break;
|
||||
}
|
||||
|
@ -172,7 +174,7 @@ switch($commentMode) {
|
|||
break;
|
||||
|
||||
case 'create':
|
||||
if(!$commentPerms['can_comment'] && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
if(!$perms->check(Perm::G_COMMENTS_CREATE) && !$categoryInfo->isOwner($currentUserInfo)) {
|
||||
echo render_info("You're not allowed to post comments.", 403);
|
||||
break;
|
||||
}
|
||||
|
@ -192,15 +194,16 @@ switch($commentMode) {
|
|||
break;
|
||||
}
|
||||
|
||||
if($categoryInfo->isLocked() && !$commentPerms['can_lock']) {
|
||||
$canLock = $perms->check(Perm::G_COMMENTS_LOCK);
|
||||
if($categoryInfo->isLocked() && !$canLock) {
|
||||
echo render_info('This comment category has been locked.', 403);
|
||||
break;
|
||||
}
|
||||
|
||||
$commentText = !empty($_POST['comment']['text']) && is_string($_POST['comment']['text']) ? $_POST['comment']['text'] : '';
|
||||
$commentReply = (string)(!empty($_POST['comment']['reply']) && is_string($_POST['comment']['reply']) ? (int)$_POST['comment']['reply'] : 0);
|
||||
$commentLock = !empty($_POST['comment']['lock']) && $commentPerms['can_lock'];
|
||||
$commentPin = !empty($_POST['comment']['pin']) && $commentPerms['can_pin'];
|
||||
$commentLock = !empty($_POST['comment']['lock']) && $canLock;
|
||||
$commentPin = !empty($_POST['comment']['pin']) && $perms->check(Perm::G_COMMENTS_PIN);
|
||||
|
||||
if($commentLock) {
|
||||
if($categoryInfo->isLocked())
|
||||
|
@ -212,7 +215,7 @@ switch($commentMode) {
|
|||
if(strlen($commentText) > 0) {
|
||||
$commentText = preg_replace("/[\r\n]{2,}/", "\n", $commentText);
|
||||
} else {
|
||||
if($commentPerms['can_lock']) {
|
||||
if($canLock) {
|
||||
echo render_info('The action has been processed.', 400);
|
||||
} else {
|
||||
echo render_info('Your comment is too short.', 400);
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use stdClass;
|
||||
use RuntimeException;
|
||||
use Index\XArray;
|
||||
|
||||
$forum = $msz->getForum();
|
||||
$users = $msz->getUsers();
|
||||
|
@ -16,18 +17,18 @@ try {
|
|||
return;
|
||||
}
|
||||
|
||||
$perms = $msz->getAuthInfo()->getPerms('forum', $categoryInfo);
|
||||
|
||||
$currentUser = $msz->getActiveUser();
|
||||
$currentUserId = $currentUser === null ? '0' : $currentUser->getId();
|
||||
|
||||
$perms = forum_perms_get_user($categoryInfo->getId(), $currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
|
||||
if(!perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM)) {
|
||||
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
||||
if(isset($currentUser) && $msz->hasActiveBan($currentUser))
|
||||
$perms &= MSZ_FORUM_PERM_LIST_FORUM | MSZ_FORUM_PERM_VIEW_FORUM;
|
||||
if($msz->hasActiveBan())
|
||||
$perms = $perms->apply(fn($calc) => $calc & (Perm::F_CATEGORY_LIST | Perm::F_CATEGORY_VIEW));
|
||||
|
||||
if($categoryInfo->isLink()) {
|
||||
if($categoryInfo->hasLinkTarget()) {
|
||||
|
@ -40,7 +41,7 @@ if($categoryInfo->isLink()) {
|
|||
$forumPagination = new Pagination($forum->countTopics(
|
||||
categoryInfo: $categoryInfo,
|
||||
global: true,
|
||||
deleted: perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST) ? null : false
|
||||
deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false
|
||||
), 20);
|
||||
|
||||
if(!$forumPagination->hasValidOffset()) {
|
||||
|
@ -56,9 +57,9 @@ $topics = [];
|
|||
if($categoryInfo->mayHaveChildren()) {
|
||||
$children = $forum->getCategoryChildren($categoryInfo, hidden: false, asTree: true);
|
||||
|
||||
foreach($children as $child) {
|
||||
$childPerms = forum_perms_get_user($child->info->getId(), (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(!perms_check($childPerms, MSZ_FORUM_PERM_LIST_FORUM)) {
|
||||
foreach($children as $childId => $child) {
|
||||
$childPerms = $msz->getAuthInfo()->getPerms('forum', $child->info);
|
||||
if(!$childPerms->check(Perm::F_CATEGORY_LIST)) {
|
||||
unset($category->children[$childId]);
|
||||
continue;
|
||||
}
|
||||
|
@ -67,8 +68,8 @@ if($categoryInfo->mayHaveChildren()) {
|
|||
|
||||
if($child->info->mayHaveChildren()) {
|
||||
foreach($child->children as $grandChildId => $grandChild) {
|
||||
$grandChildPerms = forum_perms_get_user($grandChild->info->getId(), (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(!perms_check($grandChildPerms, MSZ_FORUM_PERM_LIST_FORUM)) {
|
||||
$grandChildPerms = $msz->getAuthInfo()->getPerms('forum', $grandChild->info);
|
||||
if(!$grandChildPerms->check(Perm::F_CATEGORY_LIST)) {
|
||||
unset($child->children[$grandChildId]);
|
||||
continue;
|
||||
}
|
||||
|
@ -78,8 +79,8 @@ if($categoryInfo->mayHaveChildren()) {
|
|||
if($grandChild->info->mayHaveTopics()) {
|
||||
$catIds = [$grandChild->info->getId()];
|
||||
foreach($grandChild->childIds as $greatGrandChildId) {
|
||||
$greatGrandChildPerms = forum_perms_get_user($greatGrandChildId, (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(perms_check($greatGrandChildPerms, MSZ_FORUM_PERM_LIST_FORUM))
|
||||
$greatGrandChildPerms = $msz->getAuthInfo()->getPerms('forum', $greatGrandChildId);
|
||||
if(!$greatGrandChildPerms->check(Perm::F_CATEGORY_LIST))
|
||||
$catIds[] = $greatGrandChildId;
|
||||
}
|
||||
|
||||
|
@ -96,8 +97,8 @@ if($categoryInfo->mayHaveChildren()) {
|
|||
if($child->info->mayHaveChildren() || $child->info->mayHaveTopics()) {
|
||||
$catIds = [$child->info->getId()];
|
||||
foreach($child->childIds as $grandChildId) {
|
||||
$grandChildPerms = forum_perms_get_user($grandChildId, (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(perms_check($grandChildPerms, MSZ_FORUM_PERM_LIST_FORUM))
|
||||
$grandChildPerms = $msz->getAuthInfo()->getPerms('forum', $grandChildId);
|
||||
if($grandChildPerms->check(Perm::F_CATEGORY_LIST))
|
||||
$catIds[] = $grandChildId;
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,7 @@ if($categoryInfo->mayHaveTopics()) {
|
|||
$topicInfos = $forum->getTopics(
|
||||
categoryInfo: $categoryInfo,
|
||||
global: true,
|
||||
deleted: perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST) ? null : false,
|
||||
deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false,
|
||||
pagination: $forumPagination,
|
||||
);
|
||||
|
||||
|
@ -183,8 +184,8 @@ if($categoryInfo->mayHaveTopics()) {
|
|||
}
|
||||
}
|
||||
|
||||
$perms = perms_check_bulk($perms, [
|
||||
'can_create_topic' => MSZ_FORUM_PERM_CREATE_TOPIC,
|
||||
$perms = $perms->checkMany([
|
||||
'can_create_topic' => Perm::F_TOPIC_CREATE,
|
||||
]);
|
||||
|
||||
Template::render('forum.forum', [
|
||||
|
|
|
@ -25,8 +25,8 @@ if($mode === 'mark') {
|
|||
: $forum->getCategoryChildren(parentInfo: $categoryId, includeSelf: true);
|
||||
|
||||
foreach($categoryInfos as $categoryInfo) {
|
||||
$perms = forum_perms_get_user($categoryInfo->getId(), (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(perms_check($perms, MSZ_FORUM_PERM_LIST_FORUM))
|
||||
$perms = $msz->getAuthInfo()->getPerms('forum', $categoryInfo);
|
||||
if($perms->check(Perm::F_CATEGORY_LIST))
|
||||
$forum->updateUserReadCategory($userInfo, $categoryInfo);
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,8 @@ $userColours = [];
|
|||
$categories = $forum->getCategories(hidden: false, asTree: true);
|
||||
|
||||
foreach($categories as $categoryId => $category) {
|
||||
$perms = forum_perms_get_user($category->info->getId(), (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(!perms_check($perms, MSZ_FORUM_PERM_LIST_FORUM)) {
|
||||
$perms = $msz->getAuthInfo()->getPerms('forum', $category->info);
|
||||
if(!$perms->check(Perm::F_CATEGORY_LIST)) {
|
||||
unset($categories[$categoryId]);
|
||||
continue;
|
||||
}
|
||||
|
@ -65,8 +65,8 @@ foreach($categories as $categoryId => $category) {
|
|||
|
||||
if($category->info->mayHaveChildren())
|
||||
foreach($category->children as $childId => $child) {
|
||||
$childPerms = forum_perms_get_user($child->info->getId(), (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(!perms_check($childPerms, MSZ_FORUM_PERM_LIST_FORUM)) {
|
||||
$childPerms = $msz->getAuthInfo()->getPerms('forum', $child->info);
|
||||
if(!$childPerms->check(Perm::F_CATEGORY_LIST)) {
|
||||
unset($category->children[$childId]);
|
||||
continue;
|
||||
}
|
||||
|
@ -76,8 +76,8 @@ foreach($categories as $categoryId => $category) {
|
|||
if($category->info->isListing()) {
|
||||
if($child->info->mayHaveChildren()) {
|
||||
foreach($child->children as $grandChildId => $grandChild) {
|
||||
$grandChildPerms = forum_perms_get_user($grandChild->info->getId(), (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(!perms_check($grandChildPerms, MSZ_FORUM_PERM_LIST_FORUM)) {
|
||||
$grandChildPerms = $msz->getAuthInfo()->getPerms('forum', $grandChild->info);
|
||||
if(!$grandChildPerms->check(Perm::F_CATEGORY_LIST)) {
|
||||
unset($child->children[$grandChildId]);
|
||||
continue;
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ foreach($categories as $categoryId => $category) {
|
|||
if($grandChild->info->mayHaveTopics()) {
|
||||
$catIds = [$grandChild->info->getId()];
|
||||
foreach($grandChild->childIds as $greatGrandChildId) {
|
||||
$greatGrandChildPerms = forum_perms_get_user($greatGrandChildId, (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(perms_check($greatGrandChildPerms, MSZ_FORUM_PERM_LIST_FORUM))
|
||||
$greatGrandChildPerms = $msz->getAuthInfo()->getPerms('forum', $greatGrandChildId);
|
||||
if($greatGrandChildPerms->check(Perm::F_CATEGORY_LIST))
|
||||
$catIds[] = $greatGrandChildId;
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,8 @@ foreach($categories as $categoryId => $category) {
|
|||
if($child->info->mayHaveChildren() || $child->info->mayHaveTopics()) {
|
||||
$catIds = [$child->info->getId()];
|
||||
foreach($child->childIds as $grandChildId) {
|
||||
$grandChildPerms = forum_perms_get_user($grandChildId, (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(perms_check($grandChildPerms, MSZ_FORUM_PERM_LIST_FORUM))
|
||||
$grandChildPerms = $msz->getAuthInfo()->getPerms('forum', $grandChildId);
|
||||
if($grandChildPerms->check(Perm::F_CATEGORY_LIST))
|
||||
$catIds[] = $grandChildId;
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,8 @@ foreach($categories as $categoryId => $category) {
|
|||
if($category->info->mayHaveChildren() || $category->info->mayHaveTopics()) {
|
||||
$catIds = [$category->info->getId()];
|
||||
foreach($category->childIds as $childId) {
|
||||
$childPerms = forum_perms_get_user($childId, (int)$currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
if(perms_check($childPerms, MSZ_FORUM_PERM_LIST_FORUM))
|
||||
$childPerms = $msz->getAuthInfo()->getPerms('forum', $childId);
|
||||
if($childPerms->check(Perm::F_CATEGORY_LIST))
|
||||
$catIds[] = $childId;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_FORUM, $msz->getActiveUser()->getId(), MSZ_PERM_FORUM_VIEW_LEADERBOARD)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_FORUM_LEADERBOARD_VIEW)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -31,14 +31,14 @@ try {
|
|||
return;
|
||||
}
|
||||
|
||||
$perms = forum_perms_get_user($postInfo->getCategoryId(), $currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
$perms = $msz->getAuthInfo()->getPerms('forum', $postInfo->getCategoryId());
|
||||
|
||||
if(!perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM)) {
|
||||
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
||||
$canDeleteAny = perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST);
|
||||
$canDeleteAny = $perms->check(Perm::F_POST_DELETE_ANY);
|
||||
|
||||
switch($postMode) {
|
||||
case 'delete':
|
||||
|
@ -53,7 +53,7 @@ switch($postMode) {
|
|||
return;
|
||||
}
|
||||
|
||||
if(!perms_check($perms, MSZ_FORUM_PERM_DELETE_POST)) {
|
||||
if(!$perms->check(Perm::F_POST_DELETE_OWN)) {
|
||||
echo render_info('You are not allowed to delete posts.', 403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -121,12 +121,13 @@ if(empty($forumId)) {
|
|||
$hasCategoryInfo = true;
|
||||
}
|
||||
|
||||
$perms = forum_perms_get_user($categoryInfo->getId(), $currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
$perms = $msz->getAuthInfo()->getPerms('forum', $categoryInfo);
|
||||
|
||||
if($categoryInfo->isArchived()
|
||||
|| (isset($topicInfo) && $topicInfo->isLocked() && !perms_check($perms, MSZ_FORUM_PERM_LOCK_TOPIC))
|
||||
|| !perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM | MSZ_FORUM_PERM_CREATE_POST)
|
||||
|| (!isset($topicInfo) && !perms_check($perms, MSZ_FORUM_PERM_CREATE_TOPIC))) {
|
||||
|| (isset($topicInfo) && $topicInfo->isLocked() && !$perms->check(Perm::F_TOPIC_LOCK))
|
||||
|| !$perms->check(Perm::F_CATEGORY_VIEW)
|
||||
|| !$perms->check(Perm::F_POST_CREATE)
|
||||
|| (!isset($topicInfo) && !$perms->check(Perm::F_TOPIC_CREATE))) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
@ -141,16 +142,16 @@ $topicTypes = [];
|
|||
if($mode === 'create' || $mode === 'edit') {
|
||||
$topicTypes['discussion'] = 'Normal discussion';
|
||||
|
||||
if(perms_check($perms, MSZ_FORUM_PERM_STICKY_TOPIC))
|
||||
if($perms->check(Perm::F_TOPIC_STICKY))
|
||||
$topicTypes['sticky'] = 'Sticky topic';
|
||||
if(perms_check($perms, MSZ_FORUM_PERM_ANNOUNCE_TOPIC))
|
||||
if($perms->check(Perm::F_TOPIC_ANNOUNCE_LOCAL))
|
||||
$topicTypes['announce'] = 'Announcement';
|
||||
if(perms_check($perms, MSZ_FORUM_PERM_GLOBAL_ANNOUNCE_TOPIC))
|
||||
if($perms->check(Perm::F_TOPIC_ANNOUNCE_GLOBAL))
|
||||
$topicTypes['global'] = 'Global Announcement';
|
||||
}
|
||||
|
||||
// edit mode stuff
|
||||
if($mode === 'edit' && !perms_check($perms, $postInfo->getUserId() === $currentUserId ? MSZ_FORUM_PERM_EDIT_POST : MSZ_FORUM_PERM_EDIT_ANY_POST)) {
|
||||
if($mode === 'edit' && !$perms->check($postInfo->getUserId() === $currentUserId ? Perm::F_POST_EDIT_OWN : Perm::F_POST_EDIT_ANY)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ if($topicId < 1 && $postId > 0) {
|
|||
}
|
||||
|
||||
$categoryId = $postInfo->getCategoryId();
|
||||
$perms = forum_perms_get_user($categoryId, $currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
$canDeleteAny = !perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST);
|
||||
$perms = $msz->getAuthInfo()->getPerms('forum', $postInfo->getCategoryId());
|
||||
$canDeleteAny = $perms->check(Perm::F_POST_DELETE_ANY);
|
||||
|
||||
if($postInfo->isDeleted() && !$canDeleteAny) {
|
||||
echo render_error(404);
|
||||
|
@ -53,13 +53,13 @@ if(!$topicIsNuked) {
|
|||
|
||||
if($categoryId !== (int)$topicInfo->getCategoryId()) {
|
||||
$categoryId = (int)$topicInfo->getCategoryId();
|
||||
$perms = forum_perms_get_user($categoryId, $currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
$perms = $msz->getAuthInfo()->getPerms('forum', $topicInfo->getCategoryId());
|
||||
}
|
||||
|
||||
if(isset($currentUser) && $msz->hasActiveBan($currentUser))
|
||||
$perms &= MSZ_FORUM_PERM_LIST_FORUM | MSZ_FORUM_PERM_VIEW_FORUM;
|
||||
if($msz->hasActiveBan())
|
||||
$perms = $perms->apply(fn($calc) => $calc & (Perm::F_CATEGORY_LIST | Perm::F_CATEGORY_VIEW));
|
||||
|
||||
$canDeleteAny = perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST);
|
||||
$canDeleteAny = $perms->check(Perm::F_POST_DELETE_ANY);
|
||||
}
|
||||
|
||||
if(($topicIsNuked || $topicIsDeleted) && $forum->hasTopicRedirect($topicId)) {
|
||||
|
@ -75,7 +75,7 @@ if(($topicIsNuked || $topicIsDeleted) && $forum->hasTopicRedirect($topicId)) {
|
|||
}
|
||||
}
|
||||
|
||||
if(!perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM)) {
|
||||
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
@ -89,9 +89,9 @@ $topicIsLocked = $topicInfo->isLocked();
|
|||
$topicIsArchived = $categoryInfo->isArchived();
|
||||
$topicPostsTotal = $topicInfo->getTotalPostsCount();
|
||||
$topicIsFrozen = $topicIsArchived || $topicIsDeleted;
|
||||
$canDeleteOwn = !$topicIsFrozen && !$topicIsLocked && perms_check($perms, MSZ_FORUM_PERM_DELETE_POST);
|
||||
$canBumpTopic = !$topicIsFrozen && perms_check($perms, MSZ_FORUM_PERM_BUMP_TOPIC);
|
||||
$canLockTopic = !$topicIsFrozen && perms_check($perms, MSZ_FORUM_PERM_LOCK_TOPIC);
|
||||
$canDeleteOwn = !$topicIsFrozen && !$topicIsLocked && $perms->check(Perm::F_POST_DELETE_OWN);
|
||||
$canBumpTopic = !$topicIsFrozen && $perms->check(Perm::F_TOPIC_BUMP);
|
||||
$canLockTopic = !$topicIsFrozen && $perms->check(Perm::F_TOPIC_LOCK);
|
||||
$canNukeOrRestore = $canDeleteAny && $topicIsDeleted;
|
||||
$canDelete = !$topicIsDeleted && (
|
||||
$canDeleteAny || (
|
||||
|
@ -304,7 +304,7 @@ if(!$topicPagination->hasValidOffset()) {
|
|||
|
||||
$postInfos = $forum->getPosts(
|
||||
topicInfo: $topicInfo,
|
||||
deleted: perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST) ? null : false,
|
||||
deleted: $perms->check(Perm::F_POST_DELETE_ANY) ? null : false,
|
||||
pagination: $topicPagination,
|
||||
);
|
||||
|
||||
|
@ -343,19 +343,19 @@ foreach($postInfos as $postInfo) {
|
|||
&& $originalPostInfo->getUserId() === $postInfo->getUserId();
|
||||
}
|
||||
|
||||
$canReply = !$topicIsArchived && !$topicIsLocked && !$topicIsDeleted && perms_check($perms, MSZ_FORUM_PERM_CREATE_POST);
|
||||
$canReply = !$topicIsArchived && !$topicIsLocked && !$topicIsDeleted && $perms->check(Perm::F_POST_CREATE);
|
||||
|
||||
if(!$forum->checkUserHasReadTopic($userInfo, $topicInfo))
|
||||
$forum->incrementTopicView($topicInfo);
|
||||
|
||||
$forum->updateUserReadTopic($currentUser, $topicInfo);
|
||||
|
||||
$perms = perms_check_bulk($perms, [
|
||||
'can_create_post' => MSZ_FORUM_PERM_CREATE_POST,
|
||||
'can_edit_post' => MSZ_FORUM_PERM_EDIT_POST,
|
||||
'can_edit_any_post' => MSZ_FORUM_PERM_EDIT_ANY_POST,
|
||||
'can_delete_post' => MSZ_FORUM_PERM_DELETE_POST,
|
||||
'can_delete_any_post' => MSZ_FORUM_PERM_DELETE_ANY_POST,
|
||||
$perms = $perms->checkMany([
|
||||
'can_create_post' => Perm::F_POST_CREATE,
|
||||
'can_edit_post' => Perm::F_POST_EDIT_OWN,
|
||||
'can_edit_any_post' => Perm::F_POST_EDIT_ANY,
|
||||
'can_delete_post' => Perm::F_POST_DELETE_OWN,
|
||||
'can_delete_any_post' => Perm::F_POST_DELETE_ANY,
|
||||
]);
|
||||
|
||||
Template::render('forum.topic', [
|
||||
|
|
|
@ -7,7 +7,7 @@ use Index\DateTime;
|
|||
use Index\XArray;
|
||||
use Misuzu\Changelog\Changelog;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_CHANGELOG, $msz->getActiveUser()->getId(), MSZ_PERM_CHANGELOG_MANAGE_CHANGES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CL_CHANGES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_CHANGELOG, $msz->getActiveUser()->getId(), MSZ_PERM_CHANGELOG_MANAGE_CHANGES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CL_CHANGES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_CHANGELOG, $msz->getActiveUser()->getId(), MSZ_PERM_CHANGELOG_MANAGE_TAGS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CL_TAGS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_CHANGELOG, $msz->getActiveUser()->getId(), MSZ_PERM_CHANGELOG_MANAGE_TAGS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CL_TAGS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_FORUM_MANAGE_FORUMS)) {
|
||||
use Misuzu\Perm;
|
||||
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_FORUM_CATEGORIES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
||||
$rawPerms = perms_create(MSZ_FORUM_PERM_MODES);
|
||||
$perms = manage_forum_perms_list($rawPerms);
|
||||
$perms = $msz->getPerms();
|
||||
$permsInfos = $perms->getPermissionInfo(categoryNames: Perm::INFO_FOR_FORUM_CATEGORY);
|
||||
$permsLists = Perm::createList(Perm::LISTS_FOR_FORUM_CATEGORY);
|
||||
|
||||
if(!empty($_POST['perms']) && is_array($_POST['perms'])) {
|
||||
$finalPerms = manage_perms_apply($perms, $_POST['perms'], $rawPerms);
|
||||
$perms = manage_forum_perms_list($finalPerms);
|
||||
Template::set('calculated_perms', $finalPerms);
|
||||
}
|
||||
if(filter_has_var(INPUT_POST, 'perms'))
|
||||
Template::set('calculated_perms', Perm::convertSubmission(
|
||||
filter_input(INPUT_POST, 'perms', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY),
|
||||
Perm::INFO_FOR_FORUM_CATEGORY
|
||||
));
|
||||
|
||||
Template::render('manage.forum.listing', compact('perms'));
|
||||
Template::render('manage.forum.listing', [
|
||||
'perms_lists' => $permsLists,
|
||||
'perms_infos' => $permsInfos,
|
||||
]);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_FORUM_TOPIC_REDIRS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_FORUM_TOPIC_REDIRS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace Misuzu;
|
|||
use RuntimeException;
|
||||
use Index\XArray;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_GENERAL_MANAGE_EMOTES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_EMOTES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_GENERAL_MANAGE_EMOTES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_EMOTES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use Misuzu\Pagination;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_GENERAL_VIEW_LOGS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_LOGS_VIEW)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use Misuzu\Config\CfgTools;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_GENERAL_MANAGE_CONFIG)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CONFIG_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use Misuzu\Config\DbConfig;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_GENERAL_MANAGE_CONFIG)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CONFIG_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_GENERAL, $msz->getActiveUser()->getId(), MSZ_PERM_GENERAL_MANAGE_CONFIG)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CONFIG_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_NEWS, $msz->getActiveUser()->getId(), MSZ_PERM_NEWS_MANAGE_CATEGORIES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_NEWS_CATEGORIES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_NEWS, $msz->getActiveUser()->getId(), MSZ_PERM_NEWS_MANAGE_CATEGORIES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_NEWS_CATEGORIES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_NEWS, $msz->getActiveUser()->getId(), MSZ_PERM_NEWS_MANAGE_POSTS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_NEWS_POSTS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_NEWS, $msz->getActiveUser()->getId(), MSZ_PERM_NEWS_MANAGE_POSTS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_NEWS_POSTS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use DateTimeInterface;
|
|||
use RuntimeException;
|
||||
use Index\DateTime;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_BANS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_BANS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_BANS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_BANS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_USERS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_USERS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_NOTES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_NOTES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_NOTES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_NOTES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -4,14 +4,17 @@ namespace Misuzu;
|
|||
use RuntimeException;
|
||||
use Index\Colour\Colour;
|
||||
use Index\Colour\ColourRGB;
|
||||
use Misuzu\Perm;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_ROLES)) {
|
||||
$viewerPerms = $msz->getAuthInfo()->getPerms('user');
|
||||
if(!$viewerPerms->check(Perm::U_ROLES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
||||
$users = $msz->getUsers();
|
||||
$roles = $msz->getRoles();
|
||||
$perms = $msz->getPerms();
|
||||
|
||||
if(filter_has_var(INPUT_GET, 'r')) {
|
||||
$roleId = (string)filter_input(INPUT_GET, 'r', FILTER_SANITIZE_NUMBER_INT);
|
||||
|
@ -26,10 +29,10 @@ if(filter_has_var(INPUT_GET, 'r')) {
|
|||
} else $isNew = true;
|
||||
|
||||
$currentUser = $msz->getActiveUser();
|
||||
$canEditPerms = perms_check_user(MSZ_PERMS_USER, $currentUser->getId(), MSZ_PERM_USER_MANAGE_PERMS);
|
||||
$canEditPerms = $viewerPerms->check(Perm::U_PERMS_MANAGE);
|
||||
|
||||
if($canEditPerms)
|
||||
$permissions = manage_perms_list(perms_get_role_raw($roleId ?? 0));
|
||||
$permsInfos = $perms->getPermissionInfo(roleInfo: $roleInfo, categoryNames: Perm::INFO_FOR_ROLE);
|
||||
$permsLists = Perm::createList(Perm::LISTS_FOR_ROLE);
|
||||
|
||||
while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
|
||||
$userRank = $users->getUserRank($currentUser);
|
||||
|
@ -120,27 +123,16 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
|
|||
[$roleInfo->getId()]
|
||||
);
|
||||
|
||||
if(!empty($permissions) && !empty($_POST['perms']) && is_array($_POST['perms'])) {
|
||||
$perms = manage_perms_apply($permissions, $_POST['perms']);
|
||||
if($canEditPerms && filter_has_var(INPUT_POST, 'perms')) {
|
||||
$permsApply = Perm::convertSubmission(
|
||||
filter_input(INPUT_POST, 'perms', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY),
|
||||
Perm::INFO_FOR_ROLE
|
||||
);
|
||||
|
||||
if($perms !== null) {
|
||||
$permKeys = array_keys($perms);
|
||||
$setPermissions = DB::prepare('
|
||||
REPLACE INTO `msz_permissions` (`role_id`, `user_id`, `' . implode('`, `', $permKeys) . '`)
|
||||
VALUES (:role_id, NULL, :' . implode(', :', $permKeys) . ')
|
||||
');
|
||||
$setPermissions->bind('role_id', $roleInfo->getId());
|
||||
foreach($permsApply as $categoryName => $values)
|
||||
$perms->setPermissions($categoryName, $values['allow'], $values['deny'], roleInfo: $roleInfo);
|
||||
|
||||
foreach($perms as $key => $value) {
|
||||
$setPermissions->bind($key, $value);
|
||||
}
|
||||
|
||||
$setPermissions->execute();
|
||||
} else {
|
||||
$deletePermissions = DB::prepare('DELETE FROM `msz_permissions` WHERE `role_id` = :role_id AND `user_id` IS NULL');
|
||||
$deletePermissions->bind('role_id', $roleInfo->getId());
|
||||
$deletePermissions->execute();
|
||||
}
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
}
|
||||
|
||||
url_redirect('manage-role', ['role' => $roleInfo->getId()]);
|
||||
|
@ -150,6 +142,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
|
|||
Template::render('manage.users.role', [
|
||||
'role_new' => $isNew,
|
||||
'role_info' => $roleInfo ?? null,
|
||||
'can_manage_perms' => $canEditPerms,
|
||||
'permissions' => $permissions ?? [],
|
||||
'can_edit_perms' => $canEditPerms,
|
||||
'perms_lists' => $permsLists,
|
||||
'perms_infos' => $permsInfos,
|
||||
]);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_ROLES)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_ROLES_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
use Index\Colour\Colour;
|
||||
use Misuzu\Perm;
|
||||
use Misuzu\Auth\AuthTokenCookie;
|
||||
use Misuzu\Users\User;
|
||||
|
||||
$viewerPerms = $msz->getAuthInfo()->getPerms('user');
|
||||
if(!$msz->isLoggedIn()) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
|
@ -13,15 +15,16 @@ if(!$msz->isLoggedIn()) {
|
|||
|
||||
$users = $msz->getUsers();
|
||||
$roles = $msz->getRoles();
|
||||
$perms = $msz->getPerms();
|
||||
|
||||
$currentUser = $msz->getActiveUser();
|
||||
|
||||
$canManageUsers = perms_check_user(MSZ_PERMS_USER, $currentUser->getId(), MSZ_PERM_USER_MANAGE_USERS);
|
||||
$canManagePerms = perms_check_user(MSZ_PERMS_USER, $currentUser->getId(), MSZ_PERM_USER_MANAGE_PERMS);
|
||||
$canManageNotes = perms_check_user(MSZ_PERMS_USER, $currentUser->getId(), MSZ_PERM_USER_MANAGE_NOTES);
|
||||
$canManageWarnings = perms_check_user(MSZ_PERMS_USER, $currentUser->getId(), MSZ_PERM_USER_MANAGE_WARNINGS);
|
||||
$canManageBans = perms_check_user(MSZ_PERMS_USER, $currentUser->getId(), MSZ_PERM_USER_MANAGE_BANS);
|
||||
$canImpersonate = perms_check_user(MSZ_PERMS_USER, $currentUser->getId(), MSZ_PERM_USER_IMPERSONATE);
|
||||
$canManageUsers = $viewerPerms->check(Perm::U_USERS_MANAGE);
|
||||
$canManagePerms = $viewerPerms->check(Perm::U_PERMS_MANAGE);
|
||||
$canManageNotes = $viewerPerms->check(Perm::U_NOTES_MANAGE);
|
||||
$canManageWarnings = $viewerPerms->check(Perm::U_WARNINGS_MANAGE);
|
||||
$canManageBans = $viewerPerms->check(Perm::U_BANS_MANAGE);
|
||||
$canImpersonate = $viewerPerms->check(Perm::U_CAN_IMPERSONATE);
|
||||
$canSendTestMail = $currentUser->isSuperUser();
|
||||
$hasAccess = $canManageUsers || $canManageNotes || $canManageWarnings || $canManageBans;
|
||||
|
||||
|
@ -45,7 +48,9 @@ $userRank = $users->getUserRank($userInfo);
|
|||
|
||||
$canEdit = $canManageUsers && ($currentUser->isSuperUser() || (string)$currentUser->getId() === $userInfo->getId() || $currentUserRank > $userRank);
|
||||
$canEditPerms = $canEdit && $canManagePerms;
|
||||
$permissions = $canEditPerms ? manage_perms_list(perms_get_user_raw($userId)) : [];
|
||||
|
||||
$permsInfos = $perms->getPermissionInfo(userInfo: $userInfo, categoryNames: Perm::INFO_FOR_USER);
|
||||
$permsLists = Perm::createList(Perm::LISTS_FOR_USER);
|
||||
|
||||
if(CSRF::validateRequest() && $canEdit) {
|
||||
if(!empty($_POST['impersonate_user'])) {
|
||||
|
@ -136,11 +141,14 @@ if(CSRF::validateRequest() && $canEdit) {
|
|||
|
||||
if(!empty($addRoles))
|
||||
$users->addRoles($userInfo, $addRoles);
|
||||
|
||||
if(!empty($addRoles) || !empty($removeRoles))
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
}
|
||||
|
||||
if(!empty($_POST['user']) && is_array($_POST['user'])) {
|
||||
$setCountry = (string)($_POST['user']['country'] ?? '');
|
||||
$setTitle = (string)($_POST['user']['title'] ?? '');
|
||||
$setCountry = (string)($_POST['user']['country'] ?? '');
|
||||
$setTitle = (string)($_POST['user']['title'] ?? '');
|
||||
|
||||
$displayRole = (string)($_POST['user']['display_role'] ?? 0);
|
||||
if(!$users->hasRole($userInfo, $displayRole))
|
||||
|
@ -193,19 +201,16 @@ if(CSRF::validateRequest() && $canEdit) {
|
|||
}
|
||||
}
|
||||
|
||||
if($canEditPerms && !empty($_POST['perms']) && is_array($_POST['perms'])) {
|
||||
$perms = manage_perms_apply($permissions, $_POST['perms']);
|
||||
if($canEditPerms && filter_has_var(INPUT_POST, 'perms')) {
|
||||
$permsApply = Perm::convertSubmission(
|
||||
filter_input(INPUT_POST, 'perms', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY),
|
||||
Perm::INFO_FOR_USER
|
||||
);
|
||||
|
||||
if($perms !== null) {
|
||||
if(!perms_set_user_raw($userId, $perms))
|
||||
$notices[] = 'Failed to update permissions.';
|
||||
} else {
|
||||
if(!perms_delete_user($userId))
|
||||
$notices[] = 'Failed to remove permissions.';
|
||||
}
|
||||
foreach($permsApply as $categoryName => $values)
|
||||
$perms->setPermissions($categoryName, $values['allow'], $values['deny'], userInfo: $userInfo);
|
||||
|
||||
// this smells, make it refresh/apply in a non-retarded way
|
||||
$permissions = manage_perms_list(perms_get_user_raw($userId));
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
}
|
||||
|
||||
url_redirect('manage-user', ['user' => $userInfo->getId()]);
|
||||
|
@ -227,5 +232,6 @@ Template::render('manage.users.user', [
|
|||
'can_manage_bans' => $canManageBans,
|
||||
'can_impersonate' => $canImpersonate,
|
||||
'can_send_test_mail' => $canSendTestMail,
|
||||
'permissions' => $permissions ?? [],
|
||||
'perms_lists' => $permsLists,
|
||||
'perms_infos' => $permsInfos,
|
||||
]);
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_WARNINGS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_WARNINGS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Misuzu;
|
|||
|
||||
use RuntimeException;
|
||||
|
||||
if(!$msz->isLoggedIn() || !perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_WARNINGS)) {
|
||||
if(!$msz->getAuthInfo()->getPerms('user')->check(Perm::U_WARNINGS_MANAGE)) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -67,8 +67,6 @@ if(empty($orderDir)) {
|
|||
return;
|
||||
}
|
||||
|
||||
$canManageUsers = perms_check_user(MSZ_PERMS_USER, $msz->getActiveUser()->getId(), MSZ_PERM_USER_MANAGE_USERS);
|
||||
|
||||
if($roleId === null) {
|
||||
$roleInfo = $roles->getDefaultRole();
|
||||
} else {
|
||||
|
@ -80,6 +78,7 @@ if($roleId === null) {
|
|||
}
|
||||
}
|
||||
|
||||
$canManageUsers = $msz->getAuthInfo()->getPerms('user')->check(Perm::U_USERS_MANAGE);
|
||||
$deleted = $canManageUsers ? null : false;
|
||||
|
||||
$rolesAll = $roles->getRoles(hidden: false);
|
||||
|
|
|
@ -65,15 +65,15 @@ $notices = [];
|
|||
$userRank = $users->getUserRank($userInfo);
|
||||
$viewerRank = $viewingAsGuest ? 0 : $users->getUserRank($viewerInfo);
|
||||
|
||||
$viewerPerms = $msz->getAuthInfo()->getPerms('user');
|
||||
|
||||
$activeBanInfo = $msz->tryGetActiveBan($userInfo);
|
||||
$isBanned = $activeBanInfo !== null;
|
||||
$profileFields = $msz->getProfileFields();
|
||||
$viewingOwnProfile = (string)$viewerId === $userInfo->getId();
|
||||
$userPerms = perms_get_user($viewerId)[MSZ_PERMS_USER];
|
||||
$canManageWarnings = perms_check($userPerms, MSZ_PERM_USER_MANAGE_WARNINGS);
|
||||
$canManageWarnings = $viewerPerms->check(Perm::U_WARNINGS_MANAGE);
|
||||
$canEdit = !$viewingAsGuest && ((!$isBanned && $viewingOwnProfile) || $viewerInfo->isSuperUser() || (
|
||||
perms_check($userPerms, MSZ_PERM_USER_MANAGE_USERS)
|
||||
&& ($viewingOwnProfile || $viewerRank > $userRank)
|
||||
$viewerPerms->check(Perm::U_USERS_MANAGE) && ($viewingOwnProfile || $viewerRank > $userRank)
|
||||
));
|
||||
$avatarInfo = new UserAvatarAsset($userInfo);
|
||||
$backgroundInfo = new UserBackgroundAsset($userInfo);
|
||||
|
@ -84,13 +84,13 @@ if($isEditing) {
|
|||
return;
|
||||
}
|
||||
|
||||
$perms = perms_check_bulk($userPerms, [
|
||||
'edit_profile' => MSZ_PERM_USER_EDIT_PROFILE,
|
||||
'edit_avatar' => MSZ_PERM_USER_CHANGE_AVATAR,
|
||||
'edit_background' => MSZ_PERM_USER_CHANGE_BACKGROUND,
|
||||
'edit_about' => MSZ_PERM_USER_EDIT_ABOUT,
|
||||
'edit_birthdate' => MSZ_PERM_USER_EDIT_BIRTHDATE,
|
||||
'edit_signature' => MSZ_PERM_USER_EDIT_SIGNATURE,
|
||||
$perms = $viewerPerms->checkMany([
|
||||
'edit_profile' => Perm::U_PROFILE_EDIT,
|
||||
'edit_avatar' => Perm::U_AVATAR_CHANGE,
|
||||
'edit_background' => PERM::U_PROFILE_BACKGROUND_CHANGE,
|
||||
'edit_about' => Perm::U_PROFILE_ABOUT_EDIT,
|
||||
'edit_birthdate' => Perm::U_PROFILE_BIRTHDATE_EDIT,
|
||||
'edit_signature' => Perm::U_FORUM_SIGNATURE_EDIT,
|
||||
]);
|
||||
|
||||
Template::set([
|
||||
|
@ -105,7 +105,7 @@ if($isEditing) {
|
|||
$profileFieldsSubmit = filter_input(INPUT_POST, 'profile', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
|
||||
|
||||
if(!empty($profileFieldsSubmit)) {
|
||||
if(!$perms['edit_profile']) {
|
||||
if(!$perms->edit_profile) {
|
||||
$notices[] = 'You\'re not allowed to edit your profile';
|
||||
} else {
|
||||
$profileFieldInfos = $profileFields->getFields();
|
||||
|
@ -139,7 +139,7 @@ if($isEditing) {
|
|||
}
|
||||
|
||||
if(!empty($_POST['about']) && is_array($_POST['about'])) {
|
||||
if(!$perms['edit_about']) {
|
||||
if(!$perms->edit_about) {
|
||||
$notices[] = 'You\'re not allowed to edit your about page.';
|
||||
} else {
|
||||
$aboutText = (string)($_POST['about']['text'] ?? '');
|
||||
|
@ -163,7 +163,7 @@ if($isEditing) {
|
|||
}
|
||||
|
||||
if(!empty($_POST['signature']) && is_array($_POST['signature'])) {
|
||||
if(!$perms['edit_signature']) {
|
||||
if(!$perms->edit_signature) {
|
||||
$notices[] = 'You\'re not allowed to edit your forum signature.';
|
||||
} else {
|
||||
$sigText = (string)($_POST['signature']['text'] ?? '');
|
||||
|
@ -187,7 +187,7 @@ if($isEditing) {
|
|||
}
|
||||
|
||||
if(!empty($_POST['birthdate']) && is_array($_POST['birthdate'])) {
|
||||
if(!$perms['edit_birthdate']) {
|
||||
if(!$perms->edit_birthdate) {
|
||||
$notices[] = "You aren't allow to change your birthdate.";
|
||||
} else {
|
||||
$birthYear = (int)($_POST['birthdate']['year'] ?? 0);
|
||||
|
@ -215,7 +215,7 @@ if($isEditing) {
|
|||
if(!empty($_POST['avatar']['delete'])) {
|
||||
$avatarInfo->delete();
|
||||
} else {
|
||||
if(!$perms['edit_avatar']) {
|
||||
if(!$perms->edit_avatar) {
|
||||
$notices[] = 'You aren\'t allow to change your avatar.';
|
||||
} elseif(!empty($_FILES['avatar'])
|
||||
&& is_array($_FILES['avatar'])
|
||||
|
@ -260,7 +260,7 @@ if($isEditing) {
|
|||
if((int)($_POST['background']['attach'] ?? -1) === 0) {
|
||||
$backgroundInfo->delete();
|
||||
} else {
|
||||
if(!$perms['edit_background']) {
|
||||
if(!$perms->edit_background) {
|
||||
$notices[] = 'You aren\'t allow to change your background.';
|
||||
} elseif(!empty($_FILES['background']) && is_array($_FILES['background'])) {
|
||||
if(!empty($_FILES['background']['name']['file'])) {
|
||||
|
|
|
@ -83,7 +83,7 @@ if(!empty($searchQuery)) {
|
|||
|
||||
$forumCategoryIds = XArray::where(
|
||||
$forum->getCategories(hidden: false),
|
||||
fn($categoryInfo) => $categoryInfo->mayHaveTopics() && forum_perms_check_user(MSZ_FORUM_PERMS_GENERAL, $categoryInfo->getId(), $currentUserId, MSZ_FORUM_PERM_VIEW_FORUM)
|
||||
fn($categoryInfo) => $categoryInfo->mayHaveTopics() && $msz->getAuthInfo()->getPerms('forum', $categoryInfo)->check(Perm::F_CATEGORY_VIEW)
|
||||
);
|
||||
|
||||
$forumTopicInfos = $forum->getTopics(categoryInfo: $forumCategoryIds, deleted: false, searchQuery: $searchQueryEvaluated);
|
||||
|
|
|
@ -35,9 +35,10 @@ if(!$isRestricted && $isVerifiedRequest && !empty($_POST['role'])) {
|
|||
break;
|
||||
|
||||
case 'leave':
|
||||
if($roleInfo->isLeavable())
|
||||
if($roleInfo->isLeavable()) {
|
||||
$users->removeRoles($userInfo, $roleInfo);
|
||||
else
|
||||
$msz->getConfig()->setBoolean('perms.needsRecalc', true);
|
||||
} else
|
||||
$errors[] = "You're not allow to leave this role, an administrator has to remove it for you.";
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -125,14 +125,14 @@ if(isset($_POST['action']) && is_string($_POST['action'])) {
|
|||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'comments_categories', ['category_id:s', 'category_name:s', 'owner_id:s:n', 'category_created:t', 'category_locked:t:n'], 'owner_id');
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'comments_posts', ['comment_id:s', 'category_id:s', 'user_id:s:n', 'comment_reply_to:s:n', 'comment_text:s', 'comment_created:t', 'comment_pinned:t:n', 'comment_edited:t:n', 'comment_deleted:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'comments_votes', ['comment_id:s', 'user_id:s', 'comment_vote:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'forum_permissions', ['user_id:s:n', 'role_id:s:n', 'forum_id:s', 'forum_perms_allow:i', 'forum_perms_deny:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'forum_posts', ['post_id:s', 'topic_id:s', 'forum_id:s', 'user_id:s:n', 'post_ip:a', 'post_text:s', 'post_parse:i', 'post_display_signature:b', 'post_created:t', 'post_edited:t:n', 'post_deleted:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'forum_topics', ['topic_id:s', 'forum_id:s', 'user_id:s:n', 'topic_type:i', 'topic_title:s', 'topic_count_views:i', 'topic_created:t', 'topic_bumped:t', 'topic_deleted:t:n', 'topic_locked:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'forum_topics_redirects', ['topic_id:s', 'user_id:s:n', 'topic_redir_url:s', 'topic_redir_created:t']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'forum_topics_track', ['user_id:s', 'topic_id:s', 'forum_id:s', 'track_last_read:t']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'login_attempts', ['user_id:s:n', 'attempt_success:b', 'attempt_ip:a', 'attempt_country:s', 'attempt_created:t', 'attempt_user_agent:s']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'news_posts', ['post_id:s', 'category_id:s', 'user_id:s:n', 'comment_section_id:s:n', 'post_is_featured:b', 'post_title:s', 'post_text:s', 'post_scheduled:t', 'post_created:t', 'post_updated:t', 'post_deleted:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'permissions', ['user_id:s:n', 'role_id:s:n', 'general_perms_allow:i', 'general_perms_deny:i', 'user_perms_allow:i', 'user_perms_deny:i', 'changelog_perms_allow:i', 'changelog_perms_deny:i', 'news_perms_allow:i', 'news_perms_deny:i', 'forum_perms_allow:i', 'forum_perms_deny:i', 'comments_perms_allow:i', 'comments_perms_deny:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'perms', ['user_id:s:n', 'role_id:s:n', 'forum_id:s:n', 'perms_category:s', 'perms_allow:i', 'perms_deny:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'perms_calculated', ['user_id:s:n', 'forum_id:s:n', 'perms_category:s', 'perms_calculated:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'profile_fields_values', ['field_id:s', 'user_id:s', 'format_id:s', 'field_value:s']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'sessions', ['session_id:s', 'user_id:s', 'session_key:n', 'session_ip:a', 'session_ip_last:a:n', 'session_user_agent:s', 'session_country:s', 'session_expires:t', 'session_expires_bump:b', 'session_created:t', 'session_active:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users', ['user_id:s', 'username:s', 'password:n', 'email:s', 'register_ip:a', 'last_ip:a', 'user_super:b', 'user_country:s', 'user_colour:i:n', 'user_created:t', 'user_active:t:n', 'user_deleted:t:n', 'display_role:s:n', 'user_totp_key:n', 'user_about_content:s:n', 'user_about_parser:i', 'user_signature_content:s:n', 'user_signature_parser:i', 'user_birthdate:s:n', 'user_background_settings:i:n', 'user_title:s:n']);
|
||||
|
|
|
@ -188,8 +188,9 @@ if($inManageMode) {
|
|||
if($msz->isLoggedIn() && !$msz->hasActiveBan()) {
|
||||
$manageUser = $msz->getActiveUser();
|
||||
$manageUserId = $manageUser->getId();
|
||||
$manageGlobalPerms = $msz->getAuthInfo()->getPerms('global');
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_GENERAL, $manageUserId, MSZ_PERM_GENERAL_CAN_MANAGE)) {
|
||||
if($manageGlobalPerms->check(Perm::G_IS_JANITOR)) {
|
||||
$hasManageAccess = true;
|
||||
$manageMenu = [
|
||||
'General' => [
|
||||
|
@ -197,37 +198,38 @@ if($inManageMode) {
|
|||
],
|
||||
];
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_GENERAL, $manageUserId, MSZ_PERM_GENERAL_VIEW_LOGS))
|
||||
if($manageGlobalPerms->check(Perm::G_LOGS_VIEW))
|
||||
$manageMenu['General']['Logs'] = url('manage-general-logs');
|
||||
if(perms_check_user(MSZ_PERMS_GENERAL, $manageUserId, MSZ_PERM_GENERAL_MANAGE_EMOTES))
|
||||
if($manageGlobalPerms->check(Perm::G_EMOTES_MANAGE))
|
||||
$manageMenu['General']['Emoticons'] = url('manage-general-emoticons');
|
||||
if(perms_check_user(MSZ_PERMS_GENERAL, $manageUserId, MSZ_PERM_GENERAL_MANAGE_CONFIG))
|
||||
if($manageGlobalPerms->check(Perm::G_CONFIG_MANAGE))
|
||||
$manageMenu['General']['Settings'] = url('manage-general-settings');
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_USER, $manageUserId, MSZ_PERM_USER_MANAGE_USERS))
|
||||
$manageUserPerms = $msz->getAuthInfo()->getPerms('user');
|
||||
if($manageUserPerms->check(Perm::U_USERS_MANAGE))
|
||||
$manageMenu['Users & Roles']['Users'] = url('manage-users');
|
||||
if(perms_check_user(MSZ_PERMS_USER, $manageUserId, MSZ_PERM_USER_MANAGE_ROLES))
|
||||
if($manageUserPerms->check(Perm::U_ROLES_MANAGE))
|
||||
$manageMenu['Users & Roles']['Roles'] = url('manage-roles');
|
||||
if(perms_check_user(MSZ_PERMS_USER, $manageUserId, MSZ_PERM_USER_MANAGE_NOTES))
|
||||
if($manageUserPerms->check(Perm::U_NOTES_MANAGE))
|
||||
$manageMenu['Users & Roles']['Notes'] = url('manage-users-notes');
|
||||
if(perms_check_user(MSZ_PERMS_USER, $manageUserId, MSZ_PERM_USER_MANAGE_WARNINGS))
|
||||
if($manageUserPerms->check(Perm::U_WARNINGS_MANAGE))
|
||||
$manageMenu['Users & Roles']['Warnings'] = url('manage-users-warnings');
|
||||
if(perms_check_user(MSZ_PERMS_USER, $manageUserId, MSZ_PERM_USER_MANAGE_BANS))
|
||||
if($manageUserPerms->check(Perm::U_BANS_MANAGE))
|
||||
$manageMenu['Users & Roles']['Bans'] = url('manage-users-bans');
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_NEWS, $manageUserId, MSZ_PERM_NEWS_MANAGE_POSTS))
|
||||
if($manageGlobalPerms->check(Perm::G_NEWS_POSTS_MANAGE))
|
||||
$manageMenu['News']['Posts'] = url('manage-news-posts');
|
||||
if(perms_check_user(MSZ_PERMS_NEWS, $manageUserId, MSZ_PERM_NEWS_MANAGE_CATEGORIES))
|
||||
if($manageGlobalPerms->check(Perm::G_NEWS_CATEGORIES_MANAGE))
|
||||
$manageMenu['News']['Categories'] = url('manage-news-categories');
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_FORUM, $manageUserId, MSZ_PERM_FORUM_MANAGE_FORUMS))
|
||||
if($manageGlobalPerms->check(Perm::G_FORUM_CATEGORIES_MANAGE))
|
||||
$manageMenu['Forum']['Permission Calculator'] = url('manage-forum-categories');
|
||||
if(perms_check_user(MSZ_PERMS_FORUM, $manageUserId, MSZ_PERM_FORUM_TOPIC_REDIRS))
|
||||
if($manageGlobalPerms->check(Perm::G_FORUM_TOPIC_REDIRS_MANAGE))
|
||||
$manageMenu['Forum']['Topic Redirects'] = url('manage-forum-topic-redirs');
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_CHANGELOG, $manageUserId, MSZ_PERM_CHANGELOG_MANAGE_CHANGES))
|
||||
if($manageGlobalPerms->check(Perm::G_CL_CHANGES_MANAGE))
|
||||
$manageMenu['Changelog']['Changes'] = url('manage-changelog-changes');
|
||||
if(perms_check_user(MSZ_PERMS_CHANGELOG, $manageUserId, MSZ_PERM_CHANGELOG_MANAGE_TAGS))
|
||||
if($manageGlobalPerms->check(Perm::G_CL_TAGS_MANAGE))
|
||||
$manageMenu['Changelog']['Tags'] = url('manage-changelog-tags');
|
||||
|
||||
Template::set('manage_menu', $manageMenu);
|
||||
|
|
|
@ -1,27 +1,24 @@
|
|||
<?php
|
||||
namespace Misuzu\Auth;
|
||||
|
||||
use Index\XArray;
|
||||
use Misuzu\Auth\SessionInfo;
|
||||
use Misuzu\Forum\ForumCategoryInfo;
|
||||
use Misuzu\Perms\IPermissionResult;
|
||||
use Misuzu\Perms\Permissions;
|
||||
use Misuzu\Users\UserInfo;
|
||||
|
||||
class AuthInfo {
|
||||
private Permissions $permissions;
|
||||
private AuthTokenInfo $tokenInfo;
|
||||
private ?UserInfo $userInfo;
|
||||
private ?SessionInfo $sessionInfo;
|
||||
private ?UserInfo $realUserInfo;
|
||||
private array $perms;
|
||||
|
||||
public function __construct(
|
||||
?AuthTokenInfo $tokenInfo = null,
|
||||
?UserInfo $userInfo = null,
|
||||
?SessionInfo $sessionInfo = null,
|
||||
?UserInfo $realUserInfo = null
|
||||
) {
|
||||
$this->setInfo(
|
||||
$tokenInfo ?? AuthTokenInfo::empty(),
|
||||
$userInfo,
|
||||
$sessionInfo,
|
||||
$realUserInfo
|
||||
);
|
||||
public function __construct(Permissions $permissions) {
|
||||
$this->permissions = $permissions;
|
||||
$this->setInfo(AuthTokenInfo::empty());
|
||||
}
|
||||
|
||||
public function setInfo(
|
||||
|
@ -34,6 +31,7 @@ class AuthInfo {
|
|||
$this->userInfo = $userInfo;
|
||||
$this->sessionInfo = $sessionInfo;
|
||||
$this->realUserInfo = $realUserInfo;
|
||||
$this->perms = [];
|
||||
}
|
||||
|
||||
public function removeInfo(): void {
|
||||
|
@ -76,15 +74,17 @@ class AuthInfo {
|
|||
return $this->realUserInfo;
|
||||
}
|
||||
|
||||
private static AuthInfo $empty;
|
||||
public function getPerms(
|
||||
string $category,
|
||||
ForumCategoryInfo|string|null $forumCategoryInfo = null
|
||||
): IPermissionResult {
|
||||
$cacheKey = $category;
|
||||
if($forumCategoryInfo !== null)
|
||||
$cacheKey .= '|' . ($forumCategoryInfo instanceof ForumCategoryInfo ? $forumCategoryInfo->getId() : $forumCategoryInfo);
|
||||
|
||||
public static function init(): void {
|
||||
self::$empty = new AuthInfo(AuthTokenInfo::empty());
|
||||
}
|
||||
if(array_key_exists($cacheKey, $this->perms))
|
||||
return $this->perms[$cacheKey];
|
||||
|
||||
public static function empty(): self {
|
||||
return self::$empty;
|
||||
return $this->perms[$cacheKey] = $this->permissions->getPermissions($category, $this->userInfo, $forumCategoryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
AuthInfo::init();
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Misuzu\Comments;
|
|||
use stdClass;
|
||||
use RuntimeException;
|
||||
use Misuzu\MisuzuContext;
|
||||
use Misuzu\Perm;
|
||||
use Misuzu\Auth\AuthInfo;
|
||||
use Misuzu\Users\Users;
|
||||
|
||||
|
@ -24,7 +25,14 @@ class CommentsEx {
|
|||
$hasUser = $this->authInfo->isLoggedIn();
|
||||
$info->user = $hasUser ? $this->authInfo->getUserInfo() : null;
|
||||
$info->colour = $hasUser ? $this->users->getUserColour($info->user) : null;
|
||||
$info->perms = $hasUser ? perms_for_comments($info->user->getId()) : [];
|
||||
$info->perms = $this->authInfo->getPerms('global')->checkMany([
|
||||
'can_post' => Perm::G_COMMENTS_CREATE,
|
||||
'can_delete' => Perm::G_COMMENTS_DELETE_OWN | Perm::G_COMMENTS_DELETE_ANY,
|
||||
'can_delete_any' => Perm::G_COMMENTS_DELETE_ANY,
|
||||
'can_pin' => Perm::G_COMMENTS_PIN,
|
||||
'can_lock' => Perm::G_COMMENTS_LOCK,
|
||||
'can_vote' => Perm::G_COMMENTS_VOTE,
|
||||
]);
|
||||
$info->category = $category;
|
||||
$info->posts = [];
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ use Misuzu\Home\HomeRoutes;
|
|||
use Misuzu\Info\InfoRoutes;
|
||||
use Misuzu\News\News;
|
||||
use Misuzu\News\NewsRoutes;
|
||||
use Misuzu\Perms\Permissions;
|
||||
use Misuzu\Profile\ProfileFields;
|
||||
use Misuzu\Satori\SatoriRoutes;
|
||||
use Misuzu\SharpChat\SharpChatRoutes;
|
||||
|
@ -66,13 +67,15 @@ class MisuzuContext {
|
|||
private Counters $counters;
|
||||
private ProfileFields $profileFields;
|
||||
private Forum $forum;
|
||||
private Permissions $perms;
|
||||
private AuthInfo $authInfo;
|
||||
|
||||
public function __construct(IDbConnection $dbConn, IConfig $config) {
|
||||
$this->dbConn = $dbConn;
|
||||
$this->config = $config;
|
||||
$this->perms = new Permissions($this->dbConn);
|
||||
$this->authInfo = new AuthInfo($this->perms);
|
||||
$this->auditLog = new AuditLog($this->dbConn);
|
||||
$this->authInfo = new AuthInfo;
|
||||
$this->bans = new Bans($this->dbConn);
|
||||
$this->changelog = new Changelog($this->dbConn);
|
||||
$this->comments = new Comments($this->dbConn);
|
||||
|
@ -184,6 +187,10 @@ class MisuzuContext {
|
|||
return $this->forum;
|
||||
}
|
||||
|
||||
public function getPerms(): Permissions {
|
||||
return $this->perms;
|
||||
}
|
||||
|
||||
public function createAuthTokenPacker(): AuthTokenPacker {
|
||||
return new AuthTokenPacker($this->config->getString('auth.secret', 'meow'));
|
||||
}
|
||||
|
@ -276,7 +283,7 @@ class MisuzuContext {
|
|||
'menu' => [],
|
||||
];
|
||||
|
||||
if($hasUserInfo && perms_check_user(MSZ_PERMS_GENERAL, $userInfo->getId(), MSZ_PERM_FORUM_VIEW_LEADERBOARD))
|
||||
if($this->authInfo->getPerms('global')->check(Perm::G_FORUM_LEADERBOARD_VIEW))
|
||||
$forum['menu'][] = [
|
||||
'title' => 'Leaderboard',
|
||||
'url' => url('forum-leaderboard'),
|
||||
|
@ -325,7 +332,7 @@ class MisuzuContext {
|
|||
'icon' => 'fas fa-search fa-fw',
|
||||
];
|
||||
|
||||
if(!$this->hasActiveBan($userInfo) && perms_check_user(MSZ_PERMS_GENERAL, $userInfo->getId(), MSZ_PERM_GENERAL_CAN_MANAGE)) {
|
||||
if(!$this->hasActiveBan($userInfo) && $this->authInfo->getPerms('global')->check(Perm::G_IS_JANITOR)) {
|
||||
// restore behaviour where clicking this button switches between
|
||||
// site version and broom version
|
||||
if($inBroomCloset)
|
||||
|
@ -408,7 +415,7 @@ class MisuzuContext {
|
|||
new SharpChatRoutes(
|
||||
$this->router, $this->config->scopeTo('sockChat'),
|
||||
$this->bans, $this->emotes, $this->users,
|
||||
$this->sessions, $this->authInfo,
|
||||
$this->sessions, $this->perms, $this->authInfo,
|
||||
$this->createAuthTokenPacker(...)
|
||||
);
|
||||
|
||||
|
|
355
src/Perm.php
Normal file
355
src/Perm.php
Normal file
|
@ -0,0 +1,355 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
use stdClass;
|
||||
|
||||
// All permissions should be defined in this class
|
||||
// To avoid future conflicts, unused/deprecated permissions should remain defined for any given category
|
||||
final class Perm {
|
||||
// GLOBAL ALLOCATION:
|
||||
// 0bXXXXX_XXXXXXXX_CCCCCCCC_FFFFFFFF_NNNNNNNN_LLLLLLLL_GGGGGGGG
|
||||
// G -> General global permissions
|
||||
// L -> Changelog permissions
|
||||
// N -> News permissions
|
||||
// F -> Global Forum perms
|
||||
// C -> Global Comments perms
|
||||
// X -> unallocated
|
||||
public const G_IS_JANITOR = 0b00000_00000000_00000000_00000000_00000000_00000000_00000001;
|
||||
public const G_LOGS_VIEW = 0b00000_00000000_00000000_00000000_00000000_00000000_00000010;
|
||||
public const G_EMOTES_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000000_00000100;
|
||||
public const G_CONFIG_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000000_00001000;
|
||||
//public const G_IS_TESTER = 0b00000_00000000_00000000_00000000_00000000_00000000_00010000; // deprecated: tester status went unused
|
||||
public const G_BLACKLIST_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000000_00100000; // unused: blacklist is currently removed to reduce overhead and it seemed like it was broken
|
||||
//public const G_TWITTER_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000000_01000000; // deprecated: twitter integration has been removed
|
||||
|
||||
public const G_CL_CHANGES_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000001_00000000;
|
||||
public const G_CL_TAGS_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000010_00000000;
|
||||
//public const G_CL_ACTIONS_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000100_00000000; // deprecated: actions are hardcoded now
|
||||
|
||||
public const G_NEWS_POSTS_MANAGE = 0b00000_00000000_00000000_00000000_00000001_00000000_00000000;
|
||||
public const G_NEWS_CATEGORIES_MANAGE = 0b00000_00000000_00000000_00000000_00000010_00000000_00000000;
|
||||
|
||||
public const G_FORUM_CATEGORIES_MANAGE = 0b00000_00000000_00000000_00000001_00000000_00000000_00000000;
|
||||
public const G_FORUM_LEADERBOARD_VIEW = 0b00000_00000000_00000000_00000010_00000000_00000000_00000000;
|
||||
public const G_FORUM_TOPIC_REDIRS_MANAGE = 0b00000_00000000_00000000_00000100_00000000_00000000_00000000;
|
||||
|
||||
public const G_COMMENTS_CREATE = 0b00000_00000000_00000001_00000000_00000000_00000000_00000000;
|
||||
public const G_COMMENTS_EDIT_OWN = 0b00000_00000000_00000010_00000000_00000000_00000000_00000000; // unused: editing not implemented
|
||||
public const G_COMMENTS_EDIT_ANY = 0b00000_00000000_00000100_00000000_00000000_00000000_00000000; // unused: editing not implemented
|
||||
public const G_COMMENTS_DELETE_OWN = 0b00000_00000000_00001000_00000000_00000000_00000000_00000000;
|
||||
public const G_COMMENTS_DELETE_ANY = 0b00000_00000000_00010000_00000000_00000000_00000000_00000000;
|
||||
public const G_COMMENTS_PIN = 0b00000_00000000_00100000_00000000_00000000_00000000_00000000;
|
||||
public const G_COMMENTS_LOCK = 0b00000_00000000_01000000_00000000_00000000_00000000_00000000;
|
||||
public const G_COMMENTS_VOTE = 0b00000_00000000_10000000_00000000_00000000_00000000_00000000;
|
||||
|
||||
// USER ALLOCATION:
|
||||
// There's no rules here, manage perms started abouts halfway through the 31-bit integer
|
||||
// Maybe formally define the octets regardless later?
|
||||
public const U_PROFILE_EDIT = 0b00000_00000000_00000000_00000000_00000000_00000000_00000001;
|
||||
public const U_AVATAR_CHANGE = 0b00000_00000000_00000000_00000000_00000000_00000000_00000010;
|
||||
public const U_PROFILE_BACKGROUND_CHANGE = 0b00000_00000000_00000000_00000000_00000000_00000000_00000100;
|
||||
public const U_PROFILE_ABOUT_EDIT = 0b00000_00000000_00000000_00000000_00000000_00000000_00001000;
|
||||
public const U_PROFILE_BIRTHDATE_EDIT = 0b00000_00000000_00000000_00000000_00000000_00000000_00010000;
|
||||
public const U_FORUM_SIGNATURE_EDIT = 0b00000_00000000_00000000_00000000_00000000_00000000_00100000;
|
||||
public const U_USERS_MANAGE = 0b00000_00000000_00000000_00000000_00010000_00000000_00000000;
|
||||
public const U_ROLES_MANAGE = 0b00000_00000000_00000000_00000000_00100000_00000000_00000000;
|
||||
public const U_PERMS_MANAGE = 0b00000_00000000_00000000_00000000_01000000_00000000_00000000;
|
||||
public const U_REPORTS_MANAGE = 0b00000_00000000_00000000_00000000_10000000_00000000_00000000; // unused: reports are not implemented
|
||||
public const U_WARNINGS_MANAGE = 0b00000_00000000_00000000_00000001_00000000_00000000_00000000;
|
||||
//public const U_BLACKLISTS_MANAGE = 0b00000_00000000_00000000_00000010_00000000_00000000_00000000; // deprecated: replaced with GLOBAL_BLACKLIST_MANAGE
|
||||
public const U_NOTES_MANAGE = 0b00000_00000000_00000000_00000100_00000000_00000000_00000000;
|
||||
public const U_BANS_MANAGE = 0b00000_00000000_00000000_00001000_00000000_00000000_00000000;
|
||||
public const U_CAN_IMPERSONATE = 0b00000_00000000_00000000_00010000_00000000_00000000_00000000;
|
||||
|
||||
// FORUM ALLOCATION:
|
||||
// 0bXXXXX_XXXXXXXX_XXXXXXXX_PPPPPPPP_PPPPTTTT_TTTTTTTT_CCCCCCCC
|
||||
// C -> Category related
|
||||
// T -> Topic related
|
||||
// N -> Post related
|
||||
// X -> unallocated
|
||||
public const F_CATEGORY_LIST = 0b00000_00000000_00000000_00000000_00000000_00000000_00000001;
|
||||
public const F_CATEGORY_VIEW = 0b00000_00000000_00000000_00000000_00000000_00000000_00000010;
|
||||
public const F_TOPIC_CREATE = 0b00000_00000000_00000000_00000000_00000000_00000100_00000000;
|
||||
//public const F_TOPIC_DELETE = 0b00000_00000000_00000000_00000000_00000000_00001000_00000000; // deprecated: use F_POST_DELETE_ANY instead
|
||||
public const F_TOPIC_MOVE = 0b00000_00000000_00000000_00000000_00000000_00010000_00000000; // unused: topic moving not implemented
|
||||
public const F_TOPIC_LOCK = 0b00000_00000000_00000000_00000000_00000000_00100000_00000000;
|
||||
public const F_TOPIC_STICKY = 0b00000_00000000_00000000_00000000_00000000_01000000_00000000;
|
||||
public const F_TOPIC_ANNOUNCE_LOCAL = 0b00000_00000000_00000000_00000000_00000000_10000000_00000000;
|
||||
public const F_TOPIC_ANNOUNCE_GLOBAL = 0b00000_00000000_00000000_00000000_00000001_00000000_00000000;
|
||||
public const F_TOPIC_BUMP = 0b00000_00000000_00000000_00000000_00000010_00000000_00000000;
|
||||
public const F_TOPIC_PRIORITY_VOTE = 0b00000_00000000_00000000_00000000_00000100_00000000_00000000; // unused: feature postponed, reuse if it makes sense otherwise deprecate
|
||||
public const F_POST_CREATE = 0b00000_00000000_00000000_00000000_00010000_00000000_00000000;
|
||||
public const F_POST_EDIT_OWN = 0b00000_00000000_00000000_00000000_00100000_00000000_00000000;
|
||||
public const F_POST_EDIT_ANY = 0b00000_00000000_00000000_00000000_01000000_00000000_00000000;
|
||||
public const F_POST_DELETE_OWN = 0b00000_00000000_00000000_00000000_10000000_00000000_00000000;
|
||||
public const F_POST_DELETE_ANY = 0b00000_00000000_00000000_00000001_00000000_00000000_00000000;
|
||||
|
||||
public const INFO_FOR_USER = ['global', 'user'];
|
||||
public const INFO_FOR_ROLE = self::INFO_FOR_USER; // just alias for now, no clue if this will ever desync
|
||||
public const INFO_FOR_FORUM_CATEGORY = ['forum'];
|
||||
|
||||
public const LISTS_FOR_USER = ['global:general', 'global:changelog', 'global:news', 'global:forum', 'global:comments', 'user:personal', 'user:manage'];
|
||||
public const LISTS_FOR_ROLE = self::LISTS_FOR_USER; // idem
|
||||
public const LISTS_FOR_FORUM_CATEGORY = ['forum:category', 'forum:topic', 'forum:post'];
|
||||
|
||||
public const LISTS = [
|
||||
'global:general' => [
|
||||
'title' => 'Global Permissions',
|
||||
'perms' => [
|
||||
'global',
|
||||
self::G_IS_JANITOR,
|
||||
self::G_LOGS_VIEW,
|
||||
self::G_EMOTES_MANAGE,
|
||||
self::G_CONFIG_MANAGE,
|
||||
self::G_BLACKLIST_MANAGE,
|
||||
],
|
||||
],
|
||||
|
||||
'global:changelog' => [
|
||||
'title' => 'Changelog Permissions',
|
||||
'perms' => [
|
||||
'global',
|
||||
self::G_CL_CHANGES_MANAGE,
|
||||
self::G_CL_TAGS_MANAGE,
|
||||
],
|
||||
],
|
||||
|
||||
'global:news' => [
|
||||
'title' => 'News Permissions',
|
||||
'perms' => [
|
||||
'global',
|
||||
self::G_NEWS_POSTS_MANAGE,
|
||||
self::G_NEWS_CATEGORIES_MANAGE,
|
||||
],
|
||||
],
|
||||
|
||||
'global:forum' => [
|
||||
'title' => 'Global Forum Permissions',
|
||||
'perms' => [
|
||||
'global',
|
||||
self::G_FORUM_CATEGORIES_MANAGE,
|
||||
self::G_FORUM_LEADERBOARD_VIEW,
|
||||
self::G_FORUM_TOPIC_REDIRS_MANAGE,
|
||||
],
|
||||
],
|
||||
|
||||
'global:comments' => [
|
||||
'title' => 'Comments Permissions',
|
||||
'perms' => [
|
||||
'global',
|
||||
self::G_COMMENTS_CREATE,
|
||||
self::G_COMMENTS_EDIT_OWN,
|
||||
self::G_COMMENTS_EDIT_ANY,
|
||||
self::G_COMMENTS_DELETE_OWN,
|
||||
self::G_COMMENTS_DELETE_ANY,
|
||||
self::G_COMMENTS_PIN,
|
||||
self::G_COMMENTS_LOCK,
|
||||
self::G_COMMENTS_VOTE,
|
||||
],
|
||||
],
|
||||
|
||||
'user:personal' => [
|
||||
'title' => 'User Permissions',
|
||||
'perms' => [
|
||||
'user',
|
||||
self::U_PROFILE_EDIT,
|
||||
self::U_AVATAR_CHANGE,
|
||||
self::U_PROFILE_BACKGROUND_CHANGE,
|
||||
self::U_PROFILE_ABOUT_EDIT,
|
||||
self::U_FORUM_SIGNATURE_EDIT,
|
||||
self::U_PROFILE_BIRTHDATE_EDIT,
|
||||
],
|
||||
],
|
||||
|
||||
'user:manage' => [
|
||||
'title' => 'User Management Permissions',
|
||||
'perms' => [
|
||||
'user',
|
||||
self::U_REPORTS_MANAGE,
|
||||
self::U_NOTES_MANAGE,
|
||||
self::U_WARNINGS_MANAGE,
|
||||
self::U_BANS_MANAGE,
|
||||
self::U_USERS_MANAGE,
|
||||
self::U_ROLES_MANAGE,
|
||||
self::U_PERMS_MANAGE,
|
||||
self::U_CAN_IMPERSONATE,
|
||||
],
|
||||
],
|
||||
|
||||
'forum:category' => [
|
||||
'title' => 'Forum Category Permissions',
|
||||
'perms' => [
|
||||
'forum',
|
||||
self::F_CATEGORY_LIST,
|
||||
self::F_CATEGORY_VIEW,
|
||||
],
|
||||
],
|
||||
|
||||
'forum:topic' => [
|
||||
'title' => 'Forum Topic Permissions',
|
||||
'perms' => [
|
||||
'forum',
|
||||
self::F_TOPIC_CREATE,
|
||||
self::F_TOPIC_MOVE,
|
||||
self::F_TOPIC_LOCK,
|
||||
self::F_TOPIC_STICKY,
|
||||
self::F_TOPIC_ANNOUNCE_LOCAL,
|
||||
self::F_TOPIC_ANNOUNCE_GLOBAL,
|
||||
self::F_TOPIC_BUMP,
|
||||
self::F_TOPIC_PRIORITY_VOTE,
|
||||
],
|
||||
],
|
||||
|
||||
'forum:post' => [
|
||||
'title' => 'Forum Topic Permissions',
|
||||
'perms' => [
|
||||
'forum',
|
||||
self::F_POST_CREATE,
|
||||
self::F_POST_EDIT_OWN,
|
||||
self::F_POST_EDIT_ANY,
|
||||
self::F_POST_DELETE_OWN,
|
||||
self::F_POST_DELETE_ANY,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public const LABELS = [
|
||||
'global' => [
|
||||
self::G_IS_JANITOR => 'Can access the Broom closet.',
|
||||
self::G_LOGS_VIEW => 'Can view global audit logs.',
|
||||
self::G_EMOTES_MANAGE => 'Can manage emoticons.',
|
||||
self::G_CONFIG_MANAGE => 'Can manage global configuration.',
|
||||
//self::G_IS_TESTER => 'Can test experimental features.',
|
||||
self::G_BLACKLIST_MANAGE => 'Can manage registration IP address blacklist.',
|
||||
//self::G_TWITTER_MANAGE => 'Can manage Twitter integration settings.',
|
||||
|
||||
self::G_CL_CHANGES_MANAGE => 'Can manage changelog entries.',
|
||||
self::G_CL_TAGS_MANAGE => 'Can manage changelog tags.',
|
||||
//self::G_CL_ACTIONS_MANAGE => 'Can manage changelog action types.',
|
||||
|
||||
self::G_NEWS_POSTS_MANAGE => 'Can manage news posts.',
|
||||
self::G_NEWS_CATEGORIES_MANAGE => 'Can manage news categories.',
|
||||
|
||||
self::G_FORUM_CATEGORIES_MANAGE => 'Can manage forum categories.',
|
||||
self::G_FORUM_LEADERBOARD_VIEW => 'Can view forum leaderboard.',
|
||||
self::G_FORUM_TOPIC_REDIRS_MANAGE => 'Can create redirects for deleted forum topics.',
|
||||
|
||||
self::G_COMMENTS_CREATE => 'Can post comments.',
|
||||
self::G_COMMENTS_EDIT_OWN => 'Can edit own comments.',
|
||||
self::G_COMMENTS_EDIT_ANY => 'Can edit ANY comment.',
|
||||
self::G_COMMENTS_DELETE_OWN => 'Can delete own comments.',
|
||||
self::G_COMMENTS_DELETE_ANY => 'Can delete ANY comment.',
|
||||
self::G_COMMENTS_PIN => 'Can pin commments.',
|
||||
self::G_COMMENTS_LOCK => 'Can lock comment categories.',
|
||||
self::G_COMMENTS_VOTE => 'Can vote (like or dislike) on comments.',
|
||||
],
|
||||
|
||||
'user' => [
|
||||
self::U_PROFILE_EDIT => 'Can edit own profile.',
|
||||
self::U_AVATAR_CHANGE => 'Can change own avatar.',
|
||||
self::U_PROFILE_BACKGROUND_CHANGE => 'Can change own profile background.',
|
||||
self::U_PROFILE_ABOUT_EDIT => 'Can edit own profile about section.',
|
||||
self::U_PROFILE_BIRTHDATE_EDIT => 'Can edit own profile birthdate.',
|
||||
self::U_FORUM_SIGNATURE_EDIT => 'Can edit own forum signature.',
|
||||
|
||||
self::U_USERS_MANAGE => 'Can manage other users.',
|
||||
self::U_ROLES_MANAGE => 'Can manage user roles.',
|
||||
self::U_PERMS_MANAGE => 'Can manage permissions.',
|
||||
self::U_REPORTS_MANAGE => 'Can handle reports.',
|
||||
self::U_WARNINGS_MANAGE => 'Can manage user warnings.',
|
||||
//self::U_BLACKLISTS_MANAGE => 'Can manage registration IP address blacklist.',
|
||||
self::U_NOTES_MANAGE => 'Can manage user notes.',
|
||||
self::U_BANS_MANAGE => 'Can manage user bans.',
|
||||
self::U_CAN_IMPERSONATE => 'Can impersonate select other users. Requires whitelisting in the configuration or super user status.',
|
||||
],
|
||||
|
||||
'forum' => [
|
||||
self::F_CATEGORY_LIST => 'Can see the forum category listed but cannot access it.',
|
||||
self::F_CATEGORY_VIEW => 'Can access the forum category.',
|
||||
|
||||
self::F_TOPIC_CREATE => 'Can create forum topics.',
|
||||
//self::F_TOPIC_DELETE => 'Can delete forum topics.',
|
||||
self::F_TOPIC_MOVE => 'Can move forum topics to other categories.',
|
||||
self::F_TOPIC_LOCK => 'Can lock forum topics.',
|
||||
self::F_TOPIC_STICKY => 'Can make sticky topics.',
|
||||
self::F_TOPIC_ANNOUNCE_LOCAL => 'Can make local announcement topics.',
|
||||
self::F_TOPIC_ANNOUNCE_GLOBAL => 'Can make global announcement topics.',
|
||||
self::F_TOPIC_BUMP => 'Can bump topics without posting a reply.',
|
||||
self::F_TOPIC_PRIORITY_VOTE => 'Can use the priority voting system.',
|
||||
|
||||
self::F_POST_CREATE => 'Can create forum posts (replies only, if not allowed to create topics).',
|
||||
self::F_POST_EDIT_OWN => 'Can edit own forum posts.',
|
||||
self::F_POST_EDIT_ANY => 'Can edit ANY forum post.',
|
||||
self::F_POST_DELETE_OWN => 'Can delete own forum posts.',
|
||||
self::F_POST_DELETE_ANY => 'Can delete ANY forum post.',
|
||||
],
|
||||
];
|
||||
|
||||
public static function label(string $category, int $permission): string {
|
||||
return array_key_exists($category, self::LABELS)
|
||||
&& array_key_exists($permission, self::LABELS[$category])
|
||||
? self::LABELS[$category][$permission] : '';
|
||||
}
|
||||
|
||||
public static function createList(array $sections): array {
|
||||
$list = [];
|
||||
|
||||
foreach($sections as $sectionName) {
|
||||
if(!array_key_exists($sectionName, self::LISTS))
|
||||
continue;
|
||||
|
||||
$currentCategoryName = '';
|
||||
$sectionInfo = self::LISTS[$sectionName];
|
||||
|
||||
$list[] = $item = new stdClass;
|
||||
$item->name = $sectionName;
|
||||
$item->title = $sectionInfo['title'];
|
||||
$item->perms = [];
|
||||
|
||||
foreach($sectionInfo['perms'] as $permInfo) {
|
||||
if(is_string($permInfo)) {
|
||||
$currentCategoryName = $permInfo;
|
||||
continue;
|
||||
}
|
||||
|
||||
$categoryName = $currentCategoryName;
|
||||
$perm = 0;
|
||||
if(is_array($permInfo))
|
||||
[$categoryName, $perm] = $permInfo;
|
||||
elseif(is_int($permInfo))
|
||||
$perm = $permInfo;
|
||||
|
||||
$item->perms[] = $permItem = new stdClass;
|
||||
$permItem->category = $categoryName;
|
||||
$permItem->name = sprintf('perms[%s:%d]', $categoryName, $perm);
|
||||
$permItem->title = self::label($categoryName, $perm);
|
||||
$permItem->value = $perm;
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function convertSubmission(array $raw, array $categories): array {
|
||||
$apply = [];
|
||||
|
||||
foreach($raw as $name => $mode) {
|
||||
$nameParts = explode(':', $name, 2);
|
||||
if(count($nameParts) !== 2 || !ctype_alpha($nameParts[0]) || !ctype_digit($nameParts[1]))
|
||||
continue;
|
||||
|
||||
[$category, $value] = $nameParts;
|
||||
if(!in_array($category, $categories))
|
||||
continue;
|
||||
|
||||
if($mode === 'yes' || $mode === 'never') {
|
||||
if(!array_key_exists($category, $apply))
|
||||
$apply[$category] = ['allow' => 0, 'deny' => 0];
|
||||
|
||||
$apply[$category][$mode === 'yes' ? 'allow' : 'deny'] |= (int)$value;
|
||||
}
|
||||
}
|
||||
|
||||
return $apply;
|
||||
}
|
||||
}
|
9
src/Perms/IPermissionResult.php
Normal file
9
src/Perms/IPermissionResult.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
namespace Misuzu\Perms;
|
||||
|
||||
interface IPermissionResult {
|
||||
public function getCalculated(): int;
|
||||
public function check(int $perm): bool;
|
||||
public function checkMany(array $perms): object;
|
||||
public function apply(callable $callable): IPermissionResult;
|
||||
}
|
83
src/Perms/PermissionInfo.php
Normal file
83
src/Perms/PermissionInfo.php
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
namespace Misuzu\Perms;
|
||||
|
||||
use Index\Data\IDbResult;
|
||||
|
||||
class PermissionInfo implements IPermissionResult {
|
||||
use PermissionResultShared;
|
||||
|
||||
private ?string $userId;
|
||||
private ?string $roleId;
|
||||
private ?string $forumCategoryId;
|
||||
private string $category;
|
||||
private int $allow;
|
||||
private int $deny;
|
||||
private int $calculated;
|
||||
|
||||
public function __construct(IDbResult $result) {
|
||||
$this->userId = $result->isNull(0) ? null : $result->getInteger(0);
|
||||
$this->roleId = $result->isNull(1) ? null : $result->getInteger(1);
|
||||
$this->forumCategoryId = $result->isNull(2) ? null : $result->getInteger(2);
|
||||
$this->category = $result->getString(3);
|
||||
$this->allow = $result->getInteger(4);
|
||||
$this->deny = $result->getInteger(5);
|
||||
$this->calculated = $this->allow & ~$this->deny;
|
||||
}
|
||||
|
||||
public function hasUserId(): bool {
|
||||
return $this->userId !== null;
|
||||
}
|
||||
|
||||
public function getUserId(): ?string {
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function hasRoleId(): bool {
|
||||
return $this->roleId !== null;
|
||||
}
|
||||
|
||||
public function getRoleId(): ?string {
|
||||
return $this->roleId;
|
||||
}
|
||||
|
||||
public function hasForumCategoryId(): bool {
|
||||
return $this->forumCategoryId !== null;
|
||||
}
|
||||
|
||||
public function getForumCategoryId(): ?string {
|
||||
return $this->forumCategoryId;
|
||||
}
|
||||
|
||||
public function getCategory(): string {
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function getAllow(): int {
|
||||
return $this->allow;
|
||||
}
|
||||
|
||||
public function getDeny(): int {
|
||||
return $this->deny;
|
||||
}
|
||||
|
||||
public function getCalculated(): int {
|
||||
return $this->calculated;
|
||||
}
|
||||
|
||||
public function check(int $perm): bool {
|
||||
return ($this->calculated & $perm) > 0;
|
||||
}
|
||||
|
||||
public function checkAllow(int $perm): bool {
|
||||
return ($this->allow & $perm) > 0;
|
||||
}
|
||||
|
||||
public function checkDeny(int $perm): bool {
|
||||
return ($this->deny & $perm) > 0;
|
||||
}
|
||||
|
||||
public function checkNeutral(int $perm): bool {
|
||||
return ($this->allow & $perm) === 0
|
||||
&& ($this->deny & $perm) === 0;
|
||||
}
|
||||
}
|
16
src/Perms/PermissionResult.php
Normal file
16
src/Perms/PermissionResult.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
namespace Misuzu\Perms;
|
||||
|
||||
class PermissionResult implements IPermissionResult {
|
||||
use PermissionResultShared;
|
||||
|
||||
public function __construct(private int $calculated) {}
|
||||
|
||||
public function getCalculated(): int {
|
||||
return $this->calculated;
|
||||
}
|
||||
|
||||
public function check(int $perm): bool {
|
||||
return ($this->calculated & $perm) > 0;
|
||||
}
|
||||
}
|
24
src/Perms/PermissionResultShared.php
Normal file
24
src/Perms/PermissionResultShared.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
namespace Misuzu\Perms;
|
||||
|
||||
use stdClass;
|
||||
use InvalidArgumentException;
|
||||
|
||||
trait PermissionResultShared {
|
||||
public function checkMany(array $perms): object {
|
||||
if(empty($perms))
|
||||
throw new InvalidArgumentException('$perms must not be empty.');
|
||||
|
||||
$result = new stdClass;
|
||||
$calculated = $this->getCalculated();
|
||||
|
||||
foreach($perms as $name => $perm)
|
||||
$result->{$name} = ($calculated & $perm) > 0;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function apply(callable $callable): IPermissionResult {
|
||||
return new PermissionResult($callable($this->getCalculated()));
|
||||
}
|
||||
}
|
363
src/Perms/Permissions.php
Normal file
363
src/Perms/Permissions.php
Normal file
|
@ -0,0 +1,363 @@
|
|||
<?php
|
||||
namespace Misuzu\Perms;
|
||||
|
||||
use stdClass;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Index\DateTime;
|
||||
use Index\Data\DbStatementCache;
|
||||
use Index\Data\DbTools;
|
||||
use Index\Data\IDbConnection;
|
||||
use Index\Data\IDbStatement;
|
||||
use Misuzu\Forum\Forum;
|
||||
use Misuzu\Forum\ForumCategoryInfo;
|
||||
use Misuzu\Users\RoleInfo;
|
||||
use Misuzu\Users\UserInfo;
|
||||
|
||||
class Permissions {
|
||||
// limiting this to 53-bit in case it ever has to be sent to javascript or any other implicit float language
|
||||
// For More Information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
|
||||
// it's still a ways up from the 31-bit of the old permission system which only existed because i developed on a 32-bit laptop for a bit
|
||||
public const PERMS_MIN = 0;
|
||||
public const PERMS_MAX = 9007199254740991;
|
||||
|
||||
private IDbConnection $dbConn;
|
||||
private DbStatementCache $cache;
|
||||
|
||||
public function __construct(IDbConnection $dbConn) {
|
||||
$this->dbConn = $dbConn;
|
||||
$this->cache = new DbStatementCache($dbConn);
|
||||
}
|
||||
|
||||
// this method is purely intended for getting the permission data for a single entity
|
||||
// it should not be used to do actual permission checks
|
||||
public function getPermissionInfo(
|
||||
UserInfo|string|null $userInfo = null,
|
||||
RoleInfo|string|null $roleInfo = null,
|
||||
ForumCategoryInfo|string|null $forumCategoryInfo = null,
|
||||
array|string|null $categoryNames = null,
|
||||
): PermissionInfo|array|null {
|
||||
$hasUserInfo = $userInfo !== null;
|
||||
$hasRoleInfo = $roleInfo !== null;
|
||||
if($hasUserInfo && $hasRoleInfo)
|
||||
throw new InvalidArgumentException('$userInfo and $roleInfo may not be set at the same time.');
|
||||
|
||||
$hasForumCategoryInfo = $forumCategoryInfo !== null;
|
||||
$hasCategoryName = $categoryNames !== null;
|
||||
$categoryNamesIsArray = $hasCategoryName && is_array($categoryNames);
|
||||
if($categoryNamesIsArray && empty($categoryNames))
|
||||
throw new InvalidArgumentException('$categoryNames may not be empty if it is an array.');
|
||||
|
||||
$query = 'SELECT user_id, role_id, forum_id, perms_category, perms_allow, perms_deny FROM msz_perms';
|
||||
$query .= sprintf(' WHERE user_id %s', $hasUserInfo ? '= ?' : 'IS NULL');
|
||||
$query .= sprintf(' AND role_id %s', $hasRoleInfo ? '= ?' : 'IS NULL');
|
||||
$query .= sprintf(' AND forum_id %s', $hasForumCategoryInfo ? '= ?' : 'IS NULL');
|
||||
if($hasCategoryName)
|
||||
$query .= ' AND perms_category ' . ($categoryNamesIsArray ? sprintf('IN (%s)', DbTools::prepareListString($categoryNames)) : '= ?');
|
||||
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get($query);
|
||||
if($hasUserInfo)
|
||||
$stmt->addParameter(++$args, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
|
||||
if($hasRoleInfo)
|
||||
$stmt->addParameter(++$args, $roleInfo instanceof RoleInfo ? $roleInfo->getId() : $roleInfo);
|
||||
if($hasForumCategoryInfo)
|
||||
$stmt->addParameter(++$args, $forumCategoryInfo instanceof ForumCategoryInfo ? $forumCategoryInfo->getId() : $forumCategoryInfo);
|
||||
if($hasCategoryName) {
|
||||
if($categoryNamesIsArray) {
|
||||
foreach($categoryNames as $name)
|
||||
$stmt->addParameter(++$args, $name);
|
||||
} else
|
||||
$stmt->addParameter(++$args, $categoryNames);
|
||||
}
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
||||
if(is_string($categoryNames))
|
||||
return $result->next() ? new PermissionInfo($result) : null;
|
||||
|
||||
$perms = [];
|
||||
while($result->next())
|
||||
$perms[$result->getString(3)] = new PermissionInfo($result);
|
||||
|
||||
return $perms;
|
||||
}
|
||||
|
||||
public function setPermissions(
|
||||
string $categoryName,
|
||||
int $allow,
|
||||
int $deny,
|
||||
UserInfo|string|null $userInfo = null,
|
||||
RoleInfo|string|null $roleInfo = null,
|
||||
ForumCategoryInfo|string|null $forumCategoryInfo = null
|
||||
): void {
|
||||
if($allow < self::PERMS_MIN || $allow > self::PERMS_MAX)
|
||||
throw new InvalidArgumentException('$allow must be an positive 53-bit integer.');
|
||||
if($deny < self::PERMS_MIN || $deny > self::PERMS_MAX)
|
||||
throw new InvalidArgumentException('$allow must be an positive 53-bit integer.');
|
||||
if($userInfo !== null && $roleInfo !== null)
|
||||
throw new InvalidArgumentException('$userInfo and $roleInfo may not be set at the same time.');
|
||||
|
||||
// because of funny technical reasons we have to delete separately
|
||||
$this->removePermissions($categoryName, $userInfo, $roleInfo, $forumCategoryInfo);
|
||||
|
||||
// don't insert zeroes
|
||||
if($allow === 0 && $deny === 0)
|
||||
return;
|
||||
|
||||
$stmt = $this->cache->get('INSERT INTO msz_perms (user_id, role_id, forum_id, perms_category, perms_allow, perms_deny) VALUES (?, ?, ?, ?, ?, ?)');
|
||||
$stmt->addParameter(1, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
|
||||
$stmt->addParameter(2, $roleInfo instanceof RoleInfo ? $roleInfo->getId() : $roleInfo);
|
||||
$stmt->addParameter(3, $forumCategoryInfo instanceof ForumCategoryInfo ? $forumCategoryInfo->getId() : $forumCategoryInfo);
|
||||
$stmt->addParameter(4, $categoryName);
|
||||
$stmt->addParameter(5, $allow);
|
||||
$stmt->addParameter(6, $deny);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function removePermissions(
|
||||
array|string|null $categoryNames,
|
||||
UserInfo|string|null $userInfo = null,
|
||||
RoleInfo|string|null $roleInfo = null,
|
||||
ForumCategoryInfo|string|null $forumCategoryInfo = null
|
||||
): void {
|
||||
$hasUserInfo = $userInfo !== null;
|
||||
$hasRoleInfo = $roleInfo !== null;
|
||||
$hasForumCategoryInfo = $forumCategoryInfo !== null;
|
||||
$hasCategoryNames = $categoryNames !== null;
|
||||
$categoryNamesIsArray = $hasCategoryNames && is_array($categoryNames);
|
||||
|
||||
$query = 'DELETE FROM msz_perms';
|
||||
$query .= sprintf(' WHERE user_id %s', $hasUserInfo ? '= ?' : 'IS NULL');
|
||||
$query .= sprintf(' AND role_id %s', $hasRoleInfo ? '= ?' : 'IS NULL');
|
||||
$query .= sprintf(' AND forum_id %s', $hasForumCategoryInfo ? '= ?' : 'IS NULL');
|
||||
if($hasCategoryNames)
|
||||
$query .= ' AND perms_category ' . ($categoryNamesIsArray ? sprintf('IN (%s)', DbTools::prepareListString($categoryNames)) : '= ?');
|
||||
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get($query);
|
||||
if($hasUserInfo)
|
||||
$stmt->addParameter(++$args, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
|
||||
if($hasRoleInfo)
|
||||
$stmt->addParameter(++$args, $roleInfo instanceof RoleInfo ? $roleInfo->getId() : $roleInfo);
|
||||
if($hasForumCategoryInfo)
|
||||
$stmt->addParameter(++$args, $forumCategoryInfo instanceof ForumCategoryInfo ? $forumCategoryInfo->getId() : $forumCategoryInfo);
|
||||
if($categoryNamesIsArray) {
|
||||
foreach($categoryNames as $name)
|
||||
$stmt->addParameter(++$args, $name);
|
||||
} else
|
||||
$stmt->addParameter(++$args, $categoryNames);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function checkPermissions(
|
||||
string $categoryName,
|
||||
int $perms,
|
||||
UserInfo|string|null $userInfo = null,
|
||||
ForumCategoryInfo|string|null $forumCategoryInfo = null
|
||||
): int {
|
||||
$hasUserInfo = $userInfo !== null;
|
||||
$hasForumCategoryInfo = $forumCategoryInfo !== null;
|
||||
|
||||
$query = 'SELECT perms_calculated & ? FROM msz_perms_calculated WHERE perms_category = ?';
|
||||
$query .= sprintf(' AND forum_id %s', $hasForumCategoryInfo ? '= ?' : 'IS NULL');
|
||||
$query .= sprintf(' AND user_id %s', $hasUserInfo ? '= ?' : 'IS NULL');
|
||||
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get($query);
|
||||
$stmt->addParameter(++$args, $perms);
|
||||
$stmt->addParameter(++$args, $categoryName);
|
||||
if($hasForumCategoryInfo)
|
||||
$stmt->addParameter(++$args, $forumCategoryInfo instanceof ForumCategoryInfo ? $forumCategoryInfo->getId() : $forumCategoryInfo);
|
||||
if($hasUserInfo)
|
||||
$stmt->addParameter(++$args, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
return $result->next() ? $result->getInteger(0) : 0;
|
||||
}
|
||||
|
||||
public function getPermissions(
|
||||
string|array $categoryNames,
|
||||
UserInfo|string|null $userInfo = null,
|
||||
ForumCategoryInfo|string|null $forumCategoryInfo = null
|
||||
): PermissionResult|stdClass {
|
||||
$categoryNamesIsArray = is_array($categoryNames);
|
||||
if($categoryNamesIsArray && empty($categoryNames))
|
||||
throw new InvalidArgumentException('$categoryNames may not be an empty array.');
|
||||
|
||||
$hasUserInfo = $userInfo !== null;
|
||||
$hasForumCategoryInfo = $forumCategoryInfo !== null;
|
||||
|
||||
$query = 'SELECT perms_category, perms_calculated FROM msz_perms_calculated';
|
||||
$query .= ' WHERE perms_category ' . ($categoryNamesIsArray ? sprintf('IN (%s)', DbTools::prepareListString($categoryNames)) : '= ?');
|
||||
$query .= sprintf(' AND forum_id %s', $hasForumCategoryInfo ? '= ?' : 'IS NULL');
|
||||
$query .= sprintf(' AND user_id %s', $hasUserInfo ? '= ?' : 'IS NULL');
|
||||
$query .= ' GROUP BY perms_category';
|
||||
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get($query);
|
||||
|
||||
if($categoryNamesIsArray) {
|
||||
foreach($categoryNames as $name)
|
||||
$stmt->addParameter(++$args, $name);
|
||||
} else
|
||||
$stmt->addParameter(++$args, $categoryNames);
|
||||
if($hasForumCategoryInfo)
|
||||
$stmt->addParameter(++$args, $forumCategoryInfo instanceof ForumCategoryInfo ? $forumCategoryInfo->getId() : $forumCategoryInfo);
|
||||
if($hasUserInfo)
|
||||
$stmt->addParameter(++$args, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
if(!$categoryNamesIsArray)
|
||||
return new PermissionResult($result->next() ? $result->getInteger(1) : 0);
|
||||
|
||||
$results = [];
|
||||
while($result->next())
|
||||
$results[$result->getString(0)] = $result->getInteger(1);
|
||||
|
||||
$sets = new stdClass;
|
||||
foreach($categoryNames as $categoryName)
|
||||
$sets->{$categoryName} = new PermissionResult($results[$categoryName] ?? 0);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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...');
|
||||
$stmt = $this->cache->get('SELECT perms_category, BIT_OR(perms_allow) & ~BIT_OR(perms_deny) FROM msz_perms WHERE forum_id IS NULL AND (user_id = ? OR role_id IN (SELECT role_id FROM msz_users_roles WHERE user_id = ?)) GROUP BY perms_category');
|
||||
foreach($userIds as $userId) {
|
||||
$insert->reset();
|
||||
$insert->addParameter(1, $userId);
|
||||
$insert->addParameter(2, null);
|
||||
|
||||
$stmt->reset();
|
||||
$stmt->addParameter(1, $userId);
|
||||
$stmt->addParameter(2, $userId);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
while($result->next()) {
|
||||
$category = $result->getString(0);
|
||||
$perms = $result->getInteger(1);
|
||||
if($perms === 0)
|
||||
continue;
|
||||
|
||||
self::precalculatePermissionsLog('Inserting user #%s permissions for category %s with value %x...', $userId, $category, $perms);
|
||||
$insert->addParameter(3, $category);
|
||||
$insert->addParameter(4, $perms);
|
||||
$insert->execute();
|
||||
}
|
||||
}
|
||||
|
||||
self::precalculatePermissionsLog('Loading list of forum categories...');
|
||||
$forumCats = $forum->getCategories(asTree: true);
|
||||
foreach($forumCats as $forumCat)
|
||||
$this->precalculatePermissionsForForumCategory($insert, $userIds, $forumCat);
|
||||
|
||||
self::precalculatePermissionsLog('Finished permission precalculations!');
|
||||
}
|
||||
|
||||
private function precalculatePermissionsForForumCategory(IDbStatement $insert, array $userIds, object $forumCat, 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();
|
||||
|
||||
$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();
|
||||
}
|
||||
|
||||
$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 = ? OR role_id IN (SELECT role_id FROM msz_users_roles WHERE user_id = ?)) GROUP BY perms_category',
|
||||
DbTools::prepareListString($catIds)
|
||||
));
|
||||
foreach($catIds as $catId)
|
||||
$stmt->addParameter(++$args, $catId);
|
||||
$startArgs = $args;
|
||||
foreach($userIds as $userId) {
|
||||
$args = $startArgs;
|
||||
$stmt->addParameter(++$args, $userId);
|
||||
$stmt->addParameter(++$args, $userId);
|
||||
$stmt->execute();
|
||||
|
||||
$insert->reset();
|
||||
$insert->addParameter(1, $userId);
|
||||
$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 user #%s permissions for category %s with value %x for forum category #%s...', $userId, $category, $perms, $currentCatId);
|
||||
$insert->addParameter(3, $category);
|
||||
$insert->addParameter(4, $perms);
|
||||
$insert->execute();
|
||||
}
|
||||
}
|
||||
|
||||
foreach($forumCat->children as $forumChild)
|
||||
$this->precalculatePermissionsForForumCategory($insert, $userIds, $forumChild, $catIds);
|
||||
}
|
||||
|
||||
private static function precalculatePermissionsLog(string $fmt, ...$args): void {
|
||||
echo DateTime::now()->format('[H:i:s.u] ');
|
||||
vprintf($fmt, $args);
|
||||
echo PHP_EOL;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
namespace Misuzu\SharpChat;
|
||||
|
||||
use Misuzu\Perm;
|
||||
use Misuzu\Perms\Permissions;
|
||||
use Misuzu\Users\UserInfo;
|
||||
|
||||
final class SharpChatPerms {
|
||||
|
@ -30,25 +32,25 @@ final class SharpChatPerms {
|
|||
private const PERMS_MANAGE_FORUM = self::P_CREATE_CHANNEL | self::P_SET_CHAN_PERMA | self::P_SET_CHAN_PASS
|
||||
| self::P_SET_CHAN_HIER | self::P_DELETE_CHANNEL | self::P_JOIN_ANY_CHAN;
|
||||
|
||||
public static function convert(UserInfo $userInfo): int {
|
||||
$userInfo = (int)$userInfo->getId();
|
||||
$perms = self::PERMS_DEFAULT;
|
||||
public static function convert(Permissions $perms, UserInfo $userInfo): int {
|
||||
$perms = $perms->getPermissions(['global', 'user'], $userInfo);
|
||||
$convert = self::PERMS_DEFAULT;
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_USER, $userInfo, MSZ_PERM_USER_MANAGE_USERS))
|
||||
$perms |= self::PERMS_MANAGE_USERS;
|
||||
if($perms->user->check(Perm::U_USERS_MANAGE))
|
||||
$convert |= self::PERMS_MANAGE_USERS;
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_USER, $userInfo, MSZ_PERM_USER_MANAGE_WARNINGS))
|
||||
$perms |= self::P_KICK_USER;
|
||||
if($perms->user->check(Perm::U_WARNINGS_MANAGE))
|
||||
$convert |= self::P_KICK_USER;
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_USER, $userInfo, MSZ_PERM_USER_MANAGE_BANS))
|
||||
$perms |= self::P_BAN_USER;
|
||||
if($perms->user->check(Perm::U_BANS_MANAGE))
|
||||
$convert |= self::P_BAN_USER;
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_USER, $userInfo, MSZ_PERM_USER_CHANGE_BACKGROUND))
|
||||
$perms |= self::PERMS_CHANGE_BACKG;
|
||||
if($perms->user->check(Perm::U_PROFILE_BACKGROUND_CHANGE))
|
||||
$convert |= self::PERMS_CHANGE_BACKG;
|
||||
|
||||
if(perms_check_user(MSZ_PERMS_FORUM, $userInfo, MSZ_PERM_FORUM_MANAGE_FORUMS))
|
||||
$perms |= self::PERMS_MANAGE_FORUM;
|
||||
if($perms->global->check(Perm::G_FORUM_CATEGORIES_MANAGE))
|
||||
$convert |= self::PERMS_MANAGE_FORUM;
|
||||
|
||||
return $perms;
|
||||
return $convert;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use Misuzu\Auth\AuthInfo;
|
|||
use Misuzu\Auth\Sessions;
|
||||
use Misuzu\Config\IConfig;
|
||||
use Misuzu\Emoticons\Emotes;
|
||||
use Misuzu\Perms\Permissions;
|
||||
use Misuzu\Users\Bans;
|
||||
use Misuzu\Users\Users;
|
||||
|
||||
|
@ -19,6 +20,7 @@ final class SharpChatRoutes {
|
|||
private Emotes $emotes;
|
||||
private Users $users;
|
||||
private Sessions $sessions;
|
||||
private Permissions $perms;
|
||||
private AuthInfo $authInfo;
|
||||
private Closure $createAuthTokenPacker;
|
||||
private string $hashKey;
|
||||
|
@ -30,6 +32,7 @@ final class SharpChatRoutes {
|
|||
Emotes $emotes,
|
||||
Users $users,
|
||||
Sessions $sessions,
|
||||
Permissions $perms,
|
||||
AuthInfo $authInfo,
|
||||
Closure $createAuthTokenPacker // this sucks lol
|
||||
) {
|
||||
|
@ -38,6 +41,7 @@ final class SharpChatRoutes {
|
|||
$this->emotes = $emotes;
|
||||
$this->users = $users;
|
||||
$this->sessions = $sessions;
|
||||
$this->perms = $perms;
|
||||
$this->authInfo = $authInfo;
|
||||
$this->createAuthTokenPacker = $createAuthTokenPacker;
|
||||
$this->hashKey = $this->config->getString('hashKey', 'woomy');
|
||||
|
@ -268,7 +272,7 @@ final class SharpChatRoutes {
|
|||
'colour_raw' => Colour::toMisuzu($userColour),
|
||||
'rank' => $userRank,
|
||||
'hierarchy' => $userRank,
|
||||
'perms' => SharpChatPerms::convert($userInfo),
|
||||
'perms' => SharpChatPerms::convert($this->perms, $userInfo),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Misuzu\Users\Assets;
|
|||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Index\Routing\IRouter;
|
||||
use Misuzu\Perm;
|
||||
use Misuzu\Auth\AuthInfo;
|
||||
use Misuzu\Users\Bans;
|
||||
use Misuzu\Users\Users;
|
||||
|
@ -28,8 +29,8 @@ class AssetsRoutes {
|
|||
|
||||
private function canViewAsset($request, UserInfo $assetUser): bool {
|
||||
if($this->bans->countActiveBans($assetUser))
|
||||
return $this->authInfo->isLoggedIn() // allow staff viewing profile to still see banned user assets
|
||||
&& perms_check_user(MSZ_PERMS_USER, (int)$this->authInfo->getUserId(), MSZ_PERM_USER_MANAGE_USERS)
|
||||
// allow staff viewing profile to still see banned user assets
|
||||
return $this->authInfo->getPerms('user')->check(Perm::U_USERS_MANAGE)
|
||||
&& parse_url($request->getHeaderFirstLine('Referer'), PHP_URL_PATH) === url('user-profile');
|
||||
|
||||
return true;
|
||||
|
|
729
src/perms.php
729
src/perms.php
|
@ -1,729 +0,0 @@
|
|||
<?php
|
||||
define('MSZ_PERMS_ALLOW', 'allow');
|
||||
define('MSZ_PERMS_DENY', 'deny');
|
||||
|
||||
define('MSZ_PERMS_GENERAL', 'general');
|
||||
define('MSZ_PERM_GENERAL_CAN_MANAGE', 0x00000001);
|
||||
define('MSZ_PERM_GENERAL_VIEW_LOGS', 0x00000002);
|
||||
define('MSZ_PERM_GENERAL_MANAGE_EMOTES', 0x00000004);
|
||||
define('MSZ_PERM_GENERAL_MANAGE_CONFIG', 0x00000008);
|
||||
//define('MSZ_PERM_GENERAL_IS_TESTER', 0x00000010); Has been unused for a while
|
||||
//define('MSZ_PERM_GENERAL_MANAGE_BLACKLIST', 0x00000020); Blacklist has been removed for now to reduce overhead and because it was broken(?)
|
||||
//define('MSZ_PERM_GENERAL_MANAGE_TWITTER', 0x00000040); Twitter integration has been removed
|
||||
|
||||
define('MSZ_PERMS_USER', 'user');
|
||||
define('MSZ_PERM_USER_EDIT_PROFILE', 0x00000001);
|
||||
define('MSZ_PERM_USER_CHANGE_AVATAR', 0x00000002);
|
||||
define('MSZ_PERM_USER_CHANGE_BACKGROUND', 0x00000004);
|
||||
define('MSZ_PERM_USER_EDIT_ABOUT', 0x00000008);
|
||||
define('MSZ_PERM_USER_EDIT_BIRTHDATE', 0x00000010);
|
||||
define('MSZ_PERM_USER_EDIT_SIGNATURE', 0x00000020);
|
||||
define('MSZ_PERM_USER_MANAGE_USERS', 0x00100000);
|
||||
define('MSZ_PERM_USER_MANAGE_ROLES', 0x00200000);
|
||||
define('MSZ_PERM_USER_MANAGE_PERMS', 0x00400000);
|
||||
define('MSZ_PERM_USER_MANAGE_REPORTS', 0x00800000);
|
||||
define('MSZ_PERM_USER_MANAGE_WARNINGS', 0x01000000);
|
||||
//define('MSZ_PERM_USER_MANAGE_BLACKLISTS', 0x02000000); // Replaced with MSZ_PERM_GENERAL_MANAGE_BLACKLIST
|
||||
define('MSZ_PERM_USER_MANAGE_NOTES', 0x04000000);
|
||||
define('MSZ_PERM_USER_MANAGE_BANS', 0x08000000);
|
||||
define('MSZ_PERM_USER_IMPERSONATE', 0x10000000);
|
||||
|
||||
define('MSZ_PERMS_CHANGELOG', 'changelog');
|
||||
define('MSZ_PERM_CHANGELOG_MANAGE_CHANGES', 0x00000001);
|
||||
define('MSZ_PERM_CHANGELOG_MANAGE_TAGS', 0x00000002);
|
||||
//define('MSZ_PERM_CHANGELOG_MANAGE_ACTIONS', 0x00000004); Deprecated, actions are hardcoded now
|
||||
|
||||
define('MSZ_PERMS_NEWS', 'news');
|
||||
define('MSZ_PERM_NEWS_MANAGE_POSTS', 0x00000001);
|
||||
define('MSZ_PERM_NEWS_MANAGE_CATEGORIES', 0x00000002);
|
||||
|
||||
define('MSZ_PERMS_FORUM', 'forum');
|
||||
define('MSZ_PERM_FORUM_MANAGE_FORUMS', 0x00000001);
|
||||
define('MSZ_PERM_FORUM_VIEW_LEADERBOARD', 0x00000002);
|
||||
define('MSZ_PERM_FORUM_TOPIC_REDIRS', 0x00000004);
|
||||
|
||||
define('MSZ_PERMS_COMMENTS', 'comments');
|
||||
define('MSZ_PERM_COMMENTS_CREATE', 0x00000001);
|
||||
//define('MSZ_PERM_COMMENTS_EDIT_OWN', 0x00000002);
|
||||
//define('MSZ_PERM_COMMENTS_EDIT_ANY', 0x00000004);
|
||||
define('MSZ_PERM_COMMENTS_DELETE_OWN', 0x00000008);
|
||||
define('MSZ_PERM_COMMENTS_DELETE_ANY', 0x00000010);
|
||||
define('MSZ_PERM_COMMENTS_PIN', 0x00000020);
|
||||
define('MSZ_PERM_COMMENTS_LOCK', 0x00000040);
|
||||
define('MSZ_PERM_COMMENTS_VOTE', 0x00000080);
|
||||
|
||||
define('MSZ_PERM_MODES', [
|
||||
MSZ_PERMS_GENERAL, MSZ_PERMS_USER, MSZ_PERMS_CHANGELOG,
|
||||
MSZ_PERMS_NEWS, MSZ_PERMS_FORUM, MSZ_PERMS_COMMENTS,
|
||||
]);
|
||||
|
||||
define('MSZ_FORUM_PERMS_GENERAL', 'forum');
|
||||
|
||||
define('MSZ_FORUM_PERM_LIST_FORUM', 0x00000001); // can see stats, but will get error when trying to view
|
||||
define('MSZ_FORUM_PERM_VIEW_FORUM', 0x00000002);
|
||||
|
||||
define('MSZ_FORUM_PERM_CREATE_TOPIC', 0x00000400);
|
||||
//define('MSZ_FORUM_PERM_DELETE_TOPIC', 0x00000800); // use MSZ_FORUM_PERM_DELETE_ANY_POST instead
|
||||
define('MSZ_FORUM_PERM_MOVE_TOPIC', 0x00001000);
|
||||
define('MSZ_FORUM_PERM_LOCK_TOPIC', 0x00002000);
|
||||
define('MSZ_FORUM_PERM_STICKY_TOPIC', 0x00004000);
|
||||
define('MSZ_FORUM_PERM_ANNOUNCE_TOPIC', 0x00008000);
|
||||
define('MSZ_FORUM_PERM_GLOBAL_ANNOUNCE_TOPIC', 0x00010000);
|
||||
define('MSZ_FORUM_PERM_BUMP_TOPIC', 0x00020000);
|
||||
//define('MSZ_FORUM_PERM_PRIORITY_VOTE', 0x00040000); // feature postponed, perhaps reuse if it makes sense to
|
||||
|
||||
define('MSZ_FORUM_PERM_CREATE_POST', 0x00100000);
|
||||
define('MSZ_FORUM_PERM_EDIT_POST', 0x00200000);
|
||||
define('MSZ_FORUM_PERM_EDIT_ANY_POST', 0x00400000);
|
||||
define('MSZ_FORUM_PERM_DELETE_POST', 0x00800000);
|
||||
define('MSZ_FORUM_PERM_DELETE_ANY_POST', 0x01000000);
|
||||
|
||||
define('MSZ_FORUM_PERM_MODES', [
|
||||
MSZ_FORUM_PERMS_GENERAL,
|
||||
]);
|
||||
|
||||
function perms_get_keys(array $modes = MSZ_PERM_MODES): array {
|
||||
$perms = [];
|
||||
|
||||
foreach($modes as $mode) {
|
||||
$perms[] = perms_get_key($mode, MSZ_PERMS_ALLOW);
|
||||
$perms[] = perms_get_key($mode, MSZ_PERMS_DENY);
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
|
||||
function perms_create(array $modes = MSZ_PERM_MODES): array {
|
||||
return array_fill_keys(perms_get_keys($modes), 0);
|
||||
}
|
||||
|
||||
function perms_get_key(string $prefix, string $suffix): string {
|
||||
return $prefix . '_perms_' . $suffix;
|
||||
}
|
||||
|
||||
function perms_get_select(array $modes = MSZ_PERM_MODES, string $allow = MSZ_PERMS_ALLOW, string $deny = MSZ_PERMS_DENY): string {
|
||||
$select = '';
|
||||
|
||||
foreach($modes as $mode) {
|
||||
$select .= sprintf(
|
||||
'(BIT_OR(`%1$s_perms_%2$s`) &~ BIT_OR(`%1$s_perms_%3$s`)) AS `%1$s`,',
|
||||
$mode, $allow, $deny
|
||||
);
|
||||
}
|
||||
|
||||
$select = substr($select, 0, -1);
|
||||
|
||||
return $select;
|
||||
}
|
||||
|
||||
function perms_get_blank(array $modes = MSZ_PERM_MODES): array {
|
||||
return array_fill_keys($modes, 0);
|
||||
}
|
||||
|
||||
function perms_get_user(int|string $user): array {
|
||||
if(is_string($user))
|
||||
$user = (int)$user;
|
||||
if($user < 1)
|
||||
return perms_get_blank();
|
||||
|
||||
static $memo = [];
|
||||
|
||||
if(array_key_exists($user, $memo)) {
|
||||
return $memo[$user];
|
||||
}
|
||||
|
||||
$getPerms = \Misuzu\DB::prepare(sprintf(
|
||||
'
|
||||
SELECT %s
|
||||
FROM `msz_permissions`
|
||||
WHERE (`user_id` = :user_id_1 AND `role_id` IS NULL)
|
||||
OR (
|
||||
`user_id` IS NULL
|
||||
AND `role_id` IN (
|
||||
SELECT `role_id`
|
||||
FROM `msz_users_roles`
|
||||
WHERE `user_id` = :user_id_2
|
||||
)
|
||||
)
|
||||
',
|
||||
perms_get_select()
|
||||
));
|
||||
$getPerms->bind('user_id_1', $user);
|
||||
$getPerms->bind('user_id_2', $user);
|
||||
|
||||
return $memo[$user] = $getPerms->fetch();
|
||||
}
|
||||
|
||||
function perms_delete_user(int|string $user): bool {
|
||||
if(is_string($user))
|
||||
$user = (int)$user;
|
||||
if($user < 1)
|
||||
return false;
|
||||
|
||||
$deletePermissions = \Misuzu\DB::prepare('
|
||||
DELETE FROM `msz_permissions`
|
||||
WHERE `role_id` IS NULL
|
||||
AND `user_id` = :user_id
|
||||
');
|
||||
$deletePermissions->bind('user_id', $user);
|
||||
return $deletePermissions->execute();
|
||||
}
|
||||
|
||||
function perms_get_role(int $role): array {
|
||||
if($role < 1) {
|
||||
return perms_get_blank();
|
||||
}
|
||||
|
||||
static $memo = [];
|
||||
|
||||
if(array_key_exists($role, $memo)) {
|
||||
return $memo[$role];
|
||||
}
|
||||
|
||||
$getPerms = \Misuzu\DB::prepare(sprintf(
|
||||
'
|
||||
SELECT %s
|
||||
FROM `msz_permissions`
|
||||
WHERE `role_id` = :role_id
|
||||
AND `user_id` IS NULL
|
||||
',
|
||||
perms_get_select()
|
||||
));
|
||||
$getPerms->bind('role_id', $role);
|
||||
|
||||
return $memo[$role] = $getPerms->fetch();
|
||||
}
|
||||
|
||||
function perms_get_user_raw(int|string $user): array {
|
||||
if(is_string($user))
|
||||
$user = (int)$user;
|
||||
if($user < 1)
|
||||
return perms_create();
|
||||
|
||||
$getPerms = \Misuzu\DB::prepare(sprintf('
|
||||
SELECT `%s`
|
||||
FROM `msz_permissions`
|
||||
WHERE `user_id` = :user_id
|
||||
AND `role_id` IS NULL
|
||||
', implode('`, `', perms_get_keys())));
|
||||
$getPerms->bind('user_id', $user);
|
||||
$perms = $getPerms->fetch();
|
||||
|
||||
if(empty($perms)) {
|
||||
return perms_create();
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
|
||||
function perms_set_user_raw(int|string $user, array $perms): bool {
|
||||
if(is_string($user))
|
||||
$user = (int)$user;
|
||||
if($user < 1)
|
||||
return false;
|
||||
|
||||
$realPerms = perms_create();
|
||||
$permKeys = array_keys($realPerms);
|
||||
|
||||
foreach($permKeys as $perm) {
|
||||
$realPerms[$perm] = (int)($perms[$perm] ?? 0);
|
||||
}
|
||||
|
||||
$setPermissions = \Misuzu\DB::prepare(sprintf(
|
||||
'
|
||||
REPLACE INTO `msz_permissions`
|
||||
(`role_id`, `user_id`, `%s`)
|
||||
VALUES
|
||||
(NULL, :user_id, :%s)
|
||||
',
|
||||
implode('`, `', $permKeys),
|
||||
implode(', :', $permKeys)
|
||||
));
|
||||
$setPermissions->bind('user_id', $user);
|
||||
|
||||
foreach($realPerms as $key => $value) {
|
||||
$setPermissions->bind($key, $value);
|
||||
}
|
||||
|
||||
return $setPermissions->execute();
|
||||
}
|
||||
|
||||
function perms_get_role_raw(int $role): array {
|
||||
if($role < 1) {
|
||||
return perms_create();
|
||||
}
|
||||
|
||||
$getPerms = \Misuzu\DB::prepare(sprintf('
|
||||
SELECT `%s`
|
||||
FROM `msz_permissions`
|
||||
WHERE `user_id` IS NULL
|
||||
AND `role_id` = :role_id
|
||||
', implode('`, `', perms_get_keys())));
|
||||
$getPerms->bind('role_id', $role);
|
||||
$perms = $getPerms->fetch();
|
||||
|
||||
if(empty($perms)) {
|
||||
return perms_create();
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
|
||||
function perms_check(?int $perms, ?int $perm, bool $strict = false): bool {
|
||||
$and = ($perms ?? 0) & ($perm ?? 0);
|
||||
return $strict ? $and === $perm : $and > 0;
|
||||
}
|
||||
|
||||
function perms_check_user(string $prefix, int|string|null $userId, int $perm, bool $strict = false): bool {
|
||||
if(is_string($userId))
|
||||
$userId = (int)$userId;
|
||||
return $userId > 0 && perms_check(perms_get_user($userId)[$prefix] ?? 0, $perm, $strict);
|
||||
}
|
||||
|
||||
function perms_check_bulk(int $perms, array $set, bool $strict = false): array {
|
||||
foreach($set as $key => $perm) {
|
||||
$set[$key] = perms_check($perms, $perm, $strict);
|
||||
}
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
function perms_check_user_bulk(string $prefix, int|string|null $userId, array $set, bool $strict = false): array {
|
||||
$perms = perms_get_user($userId)[$prefix] ?? 0;
|
||||
return perms_check_bulk($perms, $set, $strict);
|
||||
}
|
||||
|
||||
function perms_for_comments(string|int $userId): array {
|
||||
return perms_check_user_bulk(MSZ_PERMS_COMMENTS, $userId, [
|
||||
'can_comment' => MSZ_PERM_COMMENTS_CREATE,
|
||||
'can_delete' => MSZ_PERM_COMMENTS_DELETE_OWN | MSZ_PERM_COMMENTS_DELETE_ANY,
|
||||
'can_delete_any' => MSZ_PERM_COMMENTS_DELETE_ANY,
|
||||
'can_pin' => MSZ_PERM_COMMENTS_PIN,
|
||||
'can_lock' => MSZ_PERM_COMMENTS_LOCK,
|
||||
'can_vote' => MSZ_PERM_COMMENTS_VOTE,
|
||||
]);
|
||||
}
|
||||
|
||||
function forum_get_parent_id(int $forumId): int {
|
||||
if($forumId < 1)
|
||||
return 0;
|
||||
|
||||
static $memoized = [];
|
||||
|
||||
if(array_key_exists($forumId, $memoized))
|
||||
return $memoized[$forumId];
|
||||
|
||||
$getParent = \Misuzu\DB::prepare('
|
||||
SELECT `forum_parent`
|
||||
FROM `msz_forum_categories`
|
||||
WHERE `forum_id` = :forum_id
|
||||
');
|
||||
$getParent->bind('forum_id', $forumId);
|
||||
|
||||
return (int)$getParent->fetchColumn();
|
||||
}
|
||||
|
||||
function forum_perms_get_user(?int $forum, int $user): array {
|
||||
$perms = perms_get_blank(MSZ_FORUM_PERM_MODES);
|
||||
|
||||
if($user < 0 || $forum < 0)
|
||||
return $perms;
|
||||
|
||||
static $memo = [];
|
||||
$memoId = "{$forum}-{$user}";
|
||||
|
||||
if(array_key_exists($memoId, $memo))
|
||||
return $memo[$memoId];
|
||||
|
||||
if($forum > 0)
|
||||
$perms = forum_perms_get_user(
|
||||
forum_get_parent_id($forum),
|
||||
$user
|
||||
);
|
||||
|
||||
$getPerms = \Misuzu\DB::prepare(sprintf(
|
||||
'
|
||||
SELECT %s
|
||||
FROM `msz_forum_permissions`
|
||||
WHERE (`forum_id` = :forum_id OR `forum_id` IS NULL)
|
||||
AND (
|
||||
(`user_id` IS NULL AND `role_id` IS NULL)
|
||||
OR (`user_id` = :user_id_1 AND `role_id` IS NULL)
|
||||
OR (
|
||||
`user_id` IS NULL
|
||||
AND `role_id` IN (
|
||||
SELECT `role_id`
|
||||
FROM `msz_users_roles`
|
||||
WHERE `user_id` = :user_id_2
|
||||
)
|
||||
)
|
||||
)
|
||||
',
|
||||
perms_get_select(MSZ_FORUM_PERM_MODES)
|
||||
));
|
||||
$getPerms->bind('forum_id', $forum);
|
||||
$getPerms->bind('user_id_1', $user);
|
||||
$getPerms->bind('user_id_2', $user);
|
||||
|
||||
$userPerms = $getPerms->fetch();
|
||||
foreach($perms as $key => $value)
|
||||
$perms[$key] |= $userPerms[$key] ?? 0;
|
||||
|
||||
return $memo[$memoId] = $perms;
|
||||
}
|
||||
|
||||
function forum_perms_check_user(
|
||||
string $prefix,
|
||||
?int $forumId,
|
||||
?int $userId,
|
||||
int $perm,
|
||||
bool $strict = false
|
||||
): bool {
|
||||
return perms_check(forum_perms_get_user($forumId, $userId)[$prefix] ?? 0, $perm, $strict);
|
||||
}
|
||||
|
||||
define('MSZ_MANAGE_PERM_YES', 'yes');
|
||||
define('MSZ_MANAGE_PERM_NO', 'no');
|
||||
define('MSZ_MANAGE_PERM_NEVER', 'never');
|
||||
|
||||
function manage_perms_value(int $perm, int $allow, int $deny): string {
|
||||
if(perms_check($deny, $perm))
|
||||
return MSZ_MANAGE_PERM_NEVER;
|
||||
if(perms_check($allow, $perm))
|
||||
return MSZ_MANAGE_PERM_YES;
|
||||
return MSZ_MANAGE_PERM_NO;
|
||||
}
|
||||
|
||||
function manage_perms_apply(array $list, array $post, ?array $raw = null): ?array {
|
||||
$perms = $raw !== null ? $raw : perms_create();
|
||||
|
||||
foreach($list as $section) {
|
||||
if(empty($post[$section['section']]) || !is_array($post[$section['section']]))
|
||||
continue;
|
||||
|
||||
$allowKey = perms_get_key($section['section'], MSZ_PERMS_ALLOW);
|
||||
$denyKey = perms_get_key($section['section'], MSZ_PERMS_DENY);
|
||||
|
||||
foreach($section['perms'] as $perm) {
|
||||
if(empty($post[$section['section']][$perm['section']]['value']))
|
||||
continue;
|
||||
$perm['perm'] = (int)$perm['perm']; // makes phpstan happy
|
||||
|
||||
switch($post[$section['section']][$perm['section']]['value']) {
|
||||
case MSZ_MANAGE_PERM_YES:
|
||||
$perms[$allowKey] |= $perm['perm'];
|
||||
$perms[$denyKey] &= ~$perm['perm'];
|
||||
break;
|
||||
|
||||
case MSZ_MANAGE_PERM_NEVER:
|
||||
$perms[$allowKey] &= ~$perm['perm'];
|
||||
$perms[$denyKey] |= $perm['perm'];
|
||||
break;
|
||||
|
||||
case MSZ_MANAGE_PERM_NO:
|
||||
default:
|
||||
$perms[$allowKey] &= ~$perm['perm'];
|
||||
$perms[$denyKey] &= ~$perm['perm'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$returnNothing = 0;
|
||||
foreach($perms as $perm)
|
||||
$returnNothing |= $perm;
|
||||
|
||||
return $returnNothing === 0 ? null : $perms;
|
||||
}
|
||||
|
||||
function manage_perms_calculate(array $rawPerms, array $perms): array {
|
||||
for($i = 0; $i < count($perms); $i++) {
|
||||
$section = $perms[$i]['section'];
|
||||
$allowKey = perms_get_key($section, MSZ_PERMS_ALLOW);
|
||||
$denyKey = perms_get_key($section, MSZ_PERMS_DENY);
|
||||
|
||||
for($j = 0; $j < count($perms[$i]['perms']); $j++) {
|
||||
$permission = $perms[$i]['perms'][$j]['perm'];
|
||||
$perms[$i]['perms'][$j]['value'] = manage_perms_value($permission, $rawPerms[$allowKey], $rawPerms[$denyKey]);
|
||||
}
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
|
||||
function manage_perms_list(array $rawPerms): array {
|
||||
return manage_perms_calculate($rawPerms, [
|
||||
[
|
||||
'section' => MSZ_PERMS_GENERAL,
|
||||
'title' => 'General',
|
||||
'perms' => [
|
||||
[
|
||||
'section' => 'can-manage',
|
||||
'title' => 'Can access the management panel.',
|
||||
'perm' => MSZ_PERM_GENERAL_CAN_MANAGE,
|
||||
],
|
||||
[
|
||||
'section' => 'view-logs',
|
||||
'title' => 'Can view audit logs.',
|
||||
'perm' => MSZ_PERM_GENERAL_VIEW_LOGS,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-emotes',
|
||||
'title' => 'Can manage emoticons.',
|
||||
'perm' => MSZ_PERM_GENERAL_MANAGE_EMOTES,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-settings',
|
||||
'title' => 'Can manage general Misuzu settings.',
|
||||
'perm' => MSZ_PERM_GENERAL_MANAGE_CONFIG,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'section' => MSZ_PERMS_USER,
|
||||
'title' => 'User',
|
||||
'perms' => [
|
||||
[
|
||||
'section' => 'edit-profile',
|
||||
'title' => 'Can edit own profile.',
|
||||
'perm' => MSZ_PERM_USER_EDIT_PROFILE,
|
||||
],
|
||||
[
|
||||
'section' => 'change-avatar',
|
||||
'title' => 'Can change own avatar.',
|
||||
'perm' => MSZ_PERM_USER_CHANGE_AVATAR,
|
||||
],
|
||||
[
|
||||
'section' => 'change-background',
|
||||
'title' => 'Can change own background.',
|
||||
'perm' => MSZ_PERM_USER_CHANGE_BACKGROUND,
|
||||
],
|
||||
[
|
||||
'section' => 'edit-about',
|
||||
'title' => 'Can change own about section.',
|
||||
'perm' => MSZ_PERM_USER_EDIT_ABOUT,
|
||||
],
|
||||
[
|
||||
'section' => 'edit-birthdate',
|
||||
'title' => 'Can change own birthdate.',
|
||||
'perm' => MSZ_PERM_USER_EDIT_BIRTHDATE,
|
||||
],
|
||||
[
|
||||
'section' => 'edit-signature',
|
||||
'title' => 'Can change own signature.',
|
||||
'perm' => MSZ_PERM_USER_EDIT_SIGNATURE,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-users',
|
||||
'title' => 'Can manage other users.',
|
||||
'perm' => MSZ_PERM_USER_MANAGE_USERS,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-roles',
|
||||
'title' => 'Can manage roles.',
|
||||
'perm' => MSZ_PERM_USER_MANAGE_ROLES,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-perms',
|
||||
'title' => 'Can manage permissions.',
|
||||
'perm' => MSZ_PERM_USER_MANAGE_PERMS,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-reports',
|
||||
'title' => 'Can handle reports.',
|
||||
'perm' => MSZ_PERM_USER_MANAGE_REPORTS,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-notes',
|
||||
'title' => 'Can manage user notes.',
|
||||
'perm' => MSZ_PERM_USER_MANAGE_NOTES,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-warnings',
|
||||
'title' => 'Can manage user warnings.',
|
||||
'perm' => MSZ_PERM_USER_MANAGE_WARNINGS,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-bans',
|
||||
'title' => 'Can manage user bans.',
|
||||
'perm' => MSZ_PERM_USER_MANAGE_BANS,
|
||||
],
|
||||
[
|
||||
'section' => 'impersonate',
|
||||
'title' => 'Can impersonate select users.',
|
||||
'perm' => MSZ_PERM_USER_IMPERSONATE,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'section' => MSZ_PERMS_NEWS,
|
||||
'title' => 'News',
|
||||
'perms' => [
|
||||
[
|
||||
'section' => 'manage-posts',
|
||||
'title' => 'Can manage posts.',
|
||||
'perm' => MSZ_PERM_NEWS_MANAGE_POSTS,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-cats',
|
||||
'title' => 'Can manage catagories.',
|
||||
'perm' => MSZ_PERM_NEWS_MANAGE_CATEGORIES,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'section' => MSZ_PERMS_FORUM,
|
||||
'title' => 'Forum',
|
||||
'perms' => [
|
||||
[
|
||||
'section' => 'manage-forums',
|
||||
'title' => 'Can manage forum sections.',
|
||||
'perm' => MSZ_PERM_FORUM_MANAGE_FORUMS,
|
||||
],
|
||||
[
|
||||
'section' => 'view-leaderboard',
|
||||
'title' => 'Can view the forum leaderboard live.',
|
||||
'perm' => MSZ_PERM_FORUM_VIEW_LEADERBOARD,
|
||||
],
|
||||
[
|
||||
'section' => 'topic-redirs',
|
||||
'title' => 'Can create redirects for deleted topics.',
|
||||
'perm' => MSZ_PERM_FORUM_TOPIC_REDIRS,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'section' => MSZ_PERMS_COMMENTS,
|
||||
'title' => 'Comments',
|
||||
'perms' => [
|
||||
[
|
||||
'section' => 'create',
|
||||
'title' => 'Can post comments.',
|
||||
'perm' => MSZ_PERM_COMMENTS_CREATE,
|
||||
],
|
||||
[
|
||||
'section' => 'delete-own',
|
||||
'title' => 'Can delete own comments.',
|
||||
'perm' => MSZ_PERM_COMMENTS_DELETE_OWN,
|
||||
],
|
||||
[
|
||||
'section' => 'delete-any',
|
||||
'title' => 'Can delete anyone\'s comments.',
|
||||
'perm' => MSZ_PERM_COMMENTS_DELETE_ANY,
|
||||
],
|
||||
[
|
||||
'section' => 'pin',
|
||||
'title' => 'Can pin comments.',
|
||||
'perm' => MSZ_PERM_COMMENTS_PIN,
|
||||
],
|
||||
[
|
||||
'section' => 'lock',
|
||||
'title' => 'Can lock comment threads.',
|
||||
'perm' => MSZ_PERM_COMMENTS_LOCK,
|
||||
],
|
||||
[
|
||||
'section' => 'vote',
|
||||
'title' => 'Can like or dislike comments.',
|
||||
'perm' => MSZ_PERM_COMMENTS_VOTE,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'section' => MSZ_PERMS_CHANGELOG,
|
||||
'title' => 'Changelog',
|
||||
'perms' => [
|
||||
[
|
||||
'section' => 'manage-changes',
|
||||
'title' => 'Can manage changes.',
|
||||
'perm' => MSZ_PERM_CHANGELOG_MANAGE_CHANGES,
|
||||
],
|
||||
[
|
||||
'section' => 'manage-tags',
|
||||
'title' => 'Can manage tags.',
|
||||
'perm' => MSZ_PERM_CHANGELOG_MANAGE_TAGS,
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
function manage_forum_perms_list(array $rawPerms): array {
|
||||
return manage_perms_calculate($rawPerms, [
|
||||
[
|
||||
'section' => MSZ_FORUM_PERMS_GENERAL,
|
||||
'title' => 'Forum',
|
||||
'perms' => [
|
||||
[
|
||||
'section' => 'can-list',
|
||||
'title' => 'Can see the forum listed, but not access it.',
|
||||
'perm' => MSZ_FORUM_PERM_LIST_FORUM,
|
||||
],
|
||||
[
|
||||
'section' => 'can-view',
|
||||
'title' => 'Can view and access the forum.',
|
||||
'perm' => MSZ_FORUM_PERM_VIEW_FORUM,
|
||||
],
|
||||
[
|
||||
'section' => 'can-create-topic',
|
||||
'title' => 'Can create topics.',
|
||||
'perm' => MSZ_FORUM_PERM_CREATE_TOPIC,
|
||||
],
|
||||
[
|
||||
'section' => 'can-move-topic',
|
||||
'title' => 'Can move topics between forums.',
|
||||
'perm' => MSZ_FORUM_PERM_MOVE_TOPIC,
|
||||
],
|
||||
[
|
||||
'section' => 'can-lock-topic',
|
||||
'title' => 'Can lock topics.',
|
||||
'perm' => MSZ_FORUM_PERM_LOCK_TOPIC,
|
||||
],
|
||||
[
|
||||
'section' => 'can-sticky-topic',
|
||||
'title' => 'Can make topics sticky.',
|
||||
'perm' => MSZ_FORUM_PERM_STICKY_TOPIC,
|
||||
],
|
||||
[
|
||||
'section' => 'can-announce-topic',
|
||||
'title' => 'Can make topics announcements.',
|
||||
'perm' => MSZ_FORUM_PERM_ANNOUNCE_TOPIC,
|
||||
],
|
||||
[
|
||||
'section' => 'can-global-announce-topic',
|
||||
'title' => 'Can make topics global announcements.',
|
||||
'perm' => MSZ_FORUM_PERM_GLOBAL_ANNOUNCE_TOPIC,
|
||||
],
|
||||
[
|
||||
'section' => 'can-bump-topic',
|
||||
'title' => 'Can bump topics without posting a reply.',
|
||||
'perm' => MSZ_FORUM_PERM_BUMP_TOPIC,
|
||||
],
|
||||
[
|
||||
'section' => 'can-create-post',
|
||||
'title' => 'Can make posts (reply only, if create topic is disallowed).',
|
||||
'perm' => MSZ_FORUM_PERM_CREATE_POST,
|
||||
],
|
||||
[
|
||||
'section' => 'can-edit-post',
|
||||
'title' => 'Can edit their own posts.',
|
||||
'perm' => MSZ_FORUM_PERM_EDIT_POST,
|
||||
],
|
||||
[
|
||||
'section' => 'can-edit-any-post',
|
||||
'title' => 'Can edit any posts.',
|
||||
'perm' => MSZ_FORUM_PERM_EDIT_ANY_POST,
|
||||
],
|
||||
[
|
||||
'section' => 'can-delete-post',
|
||||
'title' => 'Can delete own posts.',
|
||||
'perm' => MSZ_FORUM_PERM_DELETE_POST,
|
||||
],
|
||||
[
|
||||
'section' => 'can-delete-any-post',
|
||||
'title' => 'Can delete any posts.',
|
||||
'perm' => MSZ_FORUM_PERM_DELETE_ANY_POST,
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
|
@ -127,7 +127,7 @@
|
|||
{% endif %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.can_comment|default(false) %}
|
||||
{% if perms.can_post|default(false) %}
|
||||
<label class="comment__action comment__action--link" for="comment-reply-toggle-{{ comment.id }}">Reply</label>
|
||||
{% endif %}
|
||||
{% if perms.can_delete_any|default(false) or (poster.id|default(0) == user.id and perms.can_delete|default(false)) %}
|
||||
|
@ -148,7 +148,7 @@
|
|||
|
||||
<div class="comment__replies comment__replies--indent-{{ indent }}" id="comment-{{ comment.id }}-replies">
|
||||
{% from _self import comments_entry, comments_input %}
|
||||
{% if user|default(null) is not null and category|default(null) is not null and perms.can_comment|default(false) %}
|
||||
{% if user|default(null) is not null and category|default(null) is not null and perms.can_post|default(false) %}
|
||||
{{ input_checkbox_raw('', false, 'comment__reply-toggle', '', false, {'id':'comment-reply-toggle-' ~ comment.id}) }}
|
||||
{{ comments_input(category, user, perms, comment) }}
|
||||
{% endif %}
|
||||
|
@ -183,7 +183,7 @@
|
|||
<div class="comments__notice">
|
||||
This comment section was locked, <time datetime="{{ category.lockedTime|date('c') }}" title="{{ category.lockedTime|date('r') }}">{{ category.lockedTime|time_format }}</time>.
|
||||
</div>
|
||||
{% elseif not perms.can_comment|default(false) %}
|
||||
{% elseif not perms.can_post|default(false) %}
|
||||
<div class="comments__notice">
|
||||
You are not allowed to post comments.
|
||||
</div>
|
||||
|
@ -199,12 +199,6 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
{#<noscript>
|
||||
<div class="comments__javascript">
|
||||
While the comments work fine without Javascript, it is recommended you enable it as it has a lower bandwidth overhead.
|
||||
</div>
|
||||
</noscript>#}
|
||||
|
||||
<div class="comments__listing">
|
||||
{% if posts|length > 0 %}
|
||||
{% from _self import comments_entry %}
|
||||
|
|
|
@ -10,17 +10,23 @@
|
|||
|
||||
{% if calculated_perms is defined %}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th style="padding: 2px 5px;">Category</th>
|
||||
<th style="padding: 2px 5px;">Allow</th>
|
||||
<th style="padding: 2px 5px;">Deny</th>
|
||||
</tr>
|
||||
{% for key, value in calculated_perms %}
|
||||
<tr>
|
||||
<th>{{ key }}</th>
|
||||
<td><code>{{ value }}</code></td>
|
||||
<th style="padding: 2px 5px;">{{ key }}</th>
|
||||
<td style="padding: 2px 5px;"><code>{{ value.allow }}</code></td>
|
||||
<td style="padding: 2px 5px;"><code>{{ value.deny }}</code></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="">
|
||||
{{ permissions_table(perms) }}
|
||||
{{ permissions_table(perms_lists, perms_infos) }}
|
||||
<button class="input__button">Calculate</button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro permissions_table(permissions, readonly) %}
|
||||
{% macro permissions_table(lists, infos, readonly) %}
|
||||
{% from '_layout/input.twig' import input_checkbox %}
|
||||
|
||||
<div class="permissions">
|
||||
{% for perms in permissions %}
|
||||
{% for list in lists %}
|
||||
<div class="permissions__line permissions__line--header">
|
||||
<div class="permissions__title">
|
||||
{{ perms.title }}
|
||||
{{ list.title }}
|
||||
</div>
|
||||
<div class="permissions__choice">
|
||||
Yes
|
||||
|
@ -34,19 +34,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% for perm in perms.perms %}
|
||||
{% for perm in list.perms %}
|
||||
<div class="permissions__line">
|
||||
<div class="permissions__title">
|
||||
{{ perm.title }}
|
||||
</div>
|
||||
<div class="permissions__choice__wrapper">
|
||||
{{ input_checkbox('perms[' ~ perms.section ~ '][' ~ perm.section ~ '][value]', '', perm.value == 'yes', 'permissions__choice permissions__choice--radio permissions__choice--yes', 'yes', true, null, readonly) }}
|
||||
{{ input_checkbox(perm.name, '', infos[perm.category].checkAllow(perm.value) ?? false, 'permissions__choice permissions__choice--radio permissions__choice--yes', 'yes', true, null, readonly) }}
|
||||
</div>
|
||||
<div class="permissions__choice__wrapper">
|
||||
{{ input_checkbox('perms[' ~ perms.section ~ '][' ~ perm.section ~ '][value]', '', perm.value == 'no', 'permissions__choice permissions__choice--radio permissions__choice--no', 'no', true, null, readonly) }}
|
||||
{{ input_checkbox(perm.name, '', infos[perm.category].checkNeutral(perm.value) ?? true, 'permissions__choice permissions__choice--radio permissions__choice--no', 'no', true, null, readonly) }}
|
||||
</div>
|
||||
<div class="permissions__choice__wrapper">
|
||||
{{ input_checkbox('perms[' ~ perms.section ~ '][' ~ perm.section ~ '][value]', '', perm.value == 'never', 'permissions__choice permissions__choice--radio permissions__choice--never', 'never', true, null, readonly) }}
|
||||
{{ input_checkbox(perm.name, '', infos[perm.category].checkDeny(perm.value) ?? false, 'permissions__choice permissions__choice--radio permissions__choice--never', 'never', true, null, readonly) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
|
||||
<div class="container">
|
||||
{{ container_title('Permissions') }}
|
||||
{{ permissions_table(permissions, not can_manage_perms) }}
|
||||
{{ permissions_table(perms_lists, perms_infos, not can_edit_perms) }}
|
||||
</div>
|
||||
|
||||
<button class="input__button">{{ role_info is not null ? 'Update role' : 'Create role' }}</button>
|
||||
|
|
|
@ -183,11 +183,11 @@
|
|||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if permissions is not empty %}
|
||||
{% if perms_lists is defined and perms_infos is defined %}
|
||||
<form method="post" action="{{ url('manage-user', {'user': user_info.id}) }}" class="container manage__user__container">
|
||||
{{ container_title('Permissions for ' ~ user_info.name ~ ' (' ~ user_info.id ~ ')') }}
|
||||
|
||||
{{ permissions_table(permissions, not can_edit_perms) }}
|
||||
{{ permissions_table(perms_lists, perms_infos, not can_edit_perms) }}
|
||||
|
||||
{% if can_edit_perms %}
|
||||
{{ input_csrf() }}
|
||||
|
|
12
tools/cron
12
tools/cron
|
@ -81,7 +81,8 @@ msz_sched_task_func('Recount forum topics and posts.', true, function() use ($ms
|
|||
msz_sched_task_sql('Clean up expired 2fa tokens.', false,
|
||||
'DELETE FROM msz_auth_tfa WHERE tfa_created < NOW() - INTERVAL 15 MINUTE');
|
||||
|
||||
// make sure this one remains last
|
||||
// very heavy stuff that should
|
||||
|
||||
msz_sched_task_func('Resync statistics counters.', true, function() use ($msz) {
|
||||
$dbConn = $msz->getDbConn();
|
||||
$counters = $msz->getCounters();
|
||||
|
@ -139,6 +140,15 @@ msz_sched_task_func('Resync statistics counters.', true, function() use ($msz) {
|
|||
}
|
||||
});
|
||||
|
||||
msz_sched_task_func('Recalculate permissions (maybe)...', false, function() use ($msz) {
|
||||
$needsRecalc = $msz->getConfig()->getBoolean('perms.needsRecalc');
|
||||
if(!$needsRecalc)
|
||||
return;
|
||||
|
||||
$msz->getConfig()->removeValues('perms.needsRecalc');
|
||||
$msz->getPerms()->precalculatePermissions($msz->getForum());
|
||||
});
|
||||
|
||||
echo 'Running ' . count($schedTasks) . ' tasks...' . PHP_EOL;
|
||||
|
||||
$dbConn = $msz->getDbConn();
|
||||
|
|
8
tools/recalc-perms
Normal file
8
tools/recalc-perms
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
require_once __DIR__ . '/../misuzu.php';
|
||||
|
||||
$msz->getConfig()->removeValues('perms.needsRecalc');
|
||||
$msz->getPerms()->precalculatePermissions($msz->getForum());
|
Loading…
Add table
Add a link
Reference in a new issue