Rewrote forum permission backend (removed all WITH RECURSIVE statements).
This commit is contained in:
parent
7a9462d660
commit
3b84f4c9e0
16 changed files with 281 additions and 227 deletions
|
@ -3,8 +3,8 @@
|
|||
[](https://github.com/flashwave/misuzu/blob/master/LICENSE)
|
||||
|
||||
## Requirements
|
||||
- PHP 7.2
|
||||
- MySQL 8.0
|
||||
- PHP 7.3
|
||||
- MariaDB 10.3
|
||||
- [Composer](https://getcomposer.org/)
|
||||
- [node.js](https://nodejs.org/) (for the typescript and less compilers)
|
||||
- [Yarn](https://yarnpkg.com/)
|
||||
|
|
42
database/2019_04_30_190530_remove_with_recursive.php
Normal file
42
database/2019_04_30_190530_remove_with_recursive.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
namespace Misuzu\DatabaseMigrations\RemoveWithRecursive;
|
||||
|
||||
use PDO;
|
||||
|
||||
function migrate_up(PDO $conn): void
|
||||
{
|
||||
$conn->exec('DROP VIEW `msz_forum_permissions_view`');
|
||||
}
|
||||
|
||||
function migrate_down(PDO $conn): void
|
||||
{
|
||||
$conn->exec("
|
||||
CREATE VIEW `msz_forum_permissions_view` AS
|
||||
WITH RECURSIVE permissions(user_id, role_id, forum_id, forum_perms_allow, forum_perms_deny) as (
|
||||
SELECT
|
||||
pp.`user_id`, pp.`role_id`,
|
||||
pc.`forum_id`,
|
||||
IFNULL(pp.`forum_perms_allow`, 0), IFNULL(pp.`forum_perms_deny`, 0)
|
||||
FROM `msz_forum_categories` as pc
|
||||
LEFT JOIN `msz_forum_permissions` as pp
|
||||
ON pp.`forum_id` = pc.`forum_id`
|
||||
GROUP BY `user_id`, `role_id`, `forum_id`
|
||||
UNION ALL
|
||||
SELECT
|
||||
permissions.`user_id`, permissions.`role_id`,
|
||||
cc.`forum_id`,
|
||||
IFNULL(cp.`forum_perms_allow`, 0) | permissions.`forum_perms_allow`,
|
||||
IFNULL(cp.`forum_perms_deny`, 0) | permissions.`forum_perms_deny`
|
||||
FROM `msz_forum_categories` as cc
|
||||
LEFT JOIN `msz_forum_permissions` as cp
|
||||
ON cp.`forum_id` = cc.`forum_id`
|
||||
INNER JOIN permissions
|
||||
ON cc.`forum_parent` = permissions.`forum_id`
|
||||
)
|
||||
SELECT
|
||||
`user_id`, `role_id`, `forum_id`,
|
||||
(BIT_OR(`forum_perms_allow`) &~ BIT_OR(`forum_perms_deny`)) as `forum_perms`
|
||||
FROM permissions
|
||||
GROUP BY `user_id`, `role_id`, `forum_id`
|
||||
");
|
||||
}
|
|
@ -4,6 +4,11 @@ namespace Misuzu;
|
|||
define('MSZ_STARTUP', microtime(true));
|
||||
define('MSZ_ROOT', __DIR__);
|
||||
define('MSZ_DEBUG', is_file(MSZ_ROOT . '/.debug'));
|
||||
define('MSZ_PHP_MIN_VER', '7.3.0');
|
||||
|
||||
if (version_compare(PHP_VERSION, MSZ_PHP_MIN_VER, '<')) {
|
||||
die('Misuzu requires <i>at least</i> PHP <b>' . MSZ_PHP_MIN_VER . '</b> to run.');
|
||||
}
|
||||
|
||||
error_reporting(MSZ_DEBUG ? -1 : 0);
|
||||
ini_set('display_errors', MSZ_DEBUG ? 'On' : 'Off');
|
||||
|
|
|
@ -17,7 +17,7 @@ if (empty($forum) || ($forum['forum_type'] == MSZ_FORUM_TYPE_LINK && empty($foru
|
|||
return;
|
||||
}
|
||||
|
||||
$perms = forum_perms_get_user(MSZ_FORUM_PERMS_GENERAL, $forum['forum_id'], $forumUserId);
|
||||
$perms = forum_perms_get_user($forum['forum_id'], $forumUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
|
||||
if (!perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM)) {
|
||||
echo render_error(403);
|
||||
|
@ -58,11 +58,11 @@ $topics = $forumMayHaveTopics
|
|||
$forumMayHaveChildren = forum_may_have_children($forum['forum_type']);
|
||||
|
||||
if ($forumMayHaveChildren) {
|
||||
$forum['forum_subforums'] = forum_get_children($forum['forum_id'], $forumUserId, MSZ_FORUM_POSTS_PER_PAGE);
|
||||
$forum['forum_subforums'] = forum_get_children($forum['forum_id'], $forumUserId);
|
||||
|
||||
foreach ($forum['forum_subforums'] as $skey => $subforum) {
|
||||
$forum['forum_subforums'][$skey]['forum_subforums']
|
||||
= forum_get_children($subforum['forum_id'], $forumUserId, MSZ_FORUM_POSTS_PER_PAGE, true);
|
||||
= forum_get_children($subforum['forum_id'], $forumUserId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,7 @@ switch ($indexMode) {
|
|||
foreach ($categories as $key => $category) {
|
||||
$categories[$key]['forum_subforums'] = forum_get_children(
|
||||
$category['forum_id'],
|
||||
user_session_current('user_id', 0),
|
||||
perms_check($category['forum_permissions'], MSZ_FORUM_PERM_DELETE_ANY_POST)
|
||||
user_session_current('user_id', 0)
|
||||
);
|
||||
|
||||
foreach ($categories[$key]['forum_subforums'] as $skey => $sub) {
|
||||
|
@ -34,8 +33,7 @@ switch ($indexMode) {
|
|||
$categories[$key]['forum_subforums'][$skey]['forum_subforums']
|
||||
= forum_get_children(
|
||||
$sub['forum_id'],
|
||||
user_session_current('user_id', 0),
|
||||
perms_check($sub['forum_permissions'], MSZ_FORUM_PERM_DELETE_ANY_POST)
|
||||
user_session_current('user_id', 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,9 @@ if ($isXHR) {
|
|||
}
|
||||
|
||||
$postInfo = forum_post_get($postId, true);
|
||||
$perms = empty($postInfo) ? 0 : forum_perms_get_user(MSZ_FORUM_PERMS_GENERAL, $postInfo['forum_id'], $currentUserId);
|
||||
$perms = empty($postInfo)
|
||||
? 0
|
||||
: forum_perms_get_user($postInfo['forum_id'], $currentUserId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
|
||||
switch ($postMode) {
|
||||
case 'delete':
|
||||
|
@ -244,7 +246,9 @@ switch ($postMode) {
|
|||
break;
|
||||
|
||||
default: // function as an alt for topic.php?p= by default
|
||||
if (!empty($postInfo['post_deleted']) && !perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST)) {
|
||||
$canDeleteAny = perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST);
|
||||
|
||||
if (!empty($postInfo['post_deleted']) && !$canDeleteAny) {
|
||||
echo render_error(404);
|
||||
break;
|
||||
}
|
||||
|
@ -256,8 +260,13 @@ switch ($postMode) {
|
|||
break;
|
||||
}
|
||||
|
||||
if ($canDeleteAny) {
|
||||
$postInfo['preceeding_post_count'] += $postInfo['preceeding_post_deleted_count'];
|
||||
}
|
||||
|
||||
unset($postInfo['preceeding_post_deleted_count']);
|
||||
|
||||
if ($isXHR) {
|
||||
unset($postFind['can_view_deleted']);
|
||||
echo json_encode($postFind);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ if (empty($forum)) {
|
|||
return;
|
||||
}
|
||||
|
||||
$perms = forum_perms_get_user(MSZ_FORUM_PERMS_GENERAL, $forum['forum_id'], user_session_current('user_id'));
|
||||
$perms = forum_perms_get_user($forum['forum_id'], user_session_current('user_id'))[MSZ_FORUM_PERMS_GENERAL];
|
||||
|
||||
if ($forum['forum_archived']
|
||||
|| (!empty($topic['topic_locked']) && !perms_check($perms, MSZ_FORUM_PERM_LOCK_TOPIC))
|
||||
|
|
|
@ -18,7 +18,7 @@ if ($topicId < 1 && $postId > 0) {
|
|||
|
||||
$topic = forum_topic_get($topicId, true);
|
||||
$perms = $topic
|
||||
? forum_perms_get_user(MSZ_FORUM_PERMS_GENERAL, $topic['forum_id'], $topicUserId)
|
||||
? forum_perms_get_user($topic['forum_id'], $topicUserId)[MSZ_FORUM_PERMS_GENERAL]
|
||||
: 0;
|
||||
|
||||
if (user_warning_check_restriction($topicUserId)) {
|
||||
|
@ -329,7 +329,13 @@ if ($canDeleteAny) {
|
|||
$topicPagination = pagination_create($topicPosts, MSZ_FORUM_POSTS_PER_PAGE);
|
||||
|
||||
if (isset($postInfo['preceeding_post_count'])) {
|
||||
$postsPage = floor($postInfo['preceeding_post_count'] / $topicPagination['range']) + 1;
|
||||
$preceedingPosts = $postInfo['preceeding_post_count'];
|
||||
|
||||
if ($canDeleteAny) {
|
||||
$preceedingPosts += $postInfo['preceeding_post_deleted_count'];
|
||||
}
|
||||
|
||||
$postsPage = floor($preceedingPosts / $topicPagination['range']) + 1;
|
||||
}
|
||||
|
||||
$postsOffset = pagination_offset($topicPagination, $postsPage ?? pagination_param('page'));
|
||||
|
|
|
@ -4,7 +4,7 @@ require_once '../../misuzu.php';
|
|||
switch ($_GET['v'] ?? null) {
|
||||
case 'listing':
|
||||
$forums = db_query('SELECT * FROM `msz_forum_categories`');
|
||||
$rawPerms = forum_perms_create();
|
||||
$rawPerms = perms_create(MSZ_FORUM_PERM_MODES);
|
||||
$perms = manage_forum_perms_list($rawPerms);
|
||||
|
||||
if (!empty($_POST['perms']) && is_array($_POST['perms'])) {
|
||||
|
|
|
@ -119,22 +119,16 @@ function forum_get_root_categories(int $userId): array
|
|||
SELECT COUNT(`forum_id`)
|
||||
FROM `msz_forum_categories` AS sf
|
||||
WHERE sf.`forum_parent` = f.`forum_id`
|
||||
) AS `forum_children`,
|
||||
(%2$s) AS `forum_permissions`
|
||||
) AS `forum_children`
|
||||
FROM `msz_forum_categories` AS f
|
||||
WHERE f.`forum_parent` = 0
|
||||
AND f.`forum_type` = %1$d
|
||||
AND f.`forum_hidden` = 0
|
||||
GROUP BY f.`forum_id`
|
||||
HAVING (`forum_permissions` & %3$d) > 0
|
||||
ORDER BY f.`forum_order`
|
||||
',
|
||||
MSZ_FORUM_TYPE_CATEGORY,
|
||||
forum_perms_get_user_sql(MSZ_FORUM_PERMS_GENERAL, 'f.`forum_id`'),
|
||||
MSZ_FORUM_PERM_SET_READ
|
||||
MSZ_FORUM_TYPE_CATEGORY
|
||||
));
|
||||
$getCategories->bindValue('perm_user_id_user', $userId);
|
||||
$getCategories->bindValue('perm_user_id_role', $userId);
|
||||
$categories = array_merge([MSZ_FORUM_ROOT_DATA], db_fetch_all($getCategories));
|
||||
|
||||
$getRootForumCount = db_prepare(sprintf(
|
||||
|
@ -143,18 +137,20 @@ function forum_get_root_categories(int $userId): array
|
|||
FROM `msz_forum_categories`
|
||||
WHERE `forum_parent` = %d
|
||||
AND `forum_type` != %d
|
||||
AND (%s & %d) > 0
|
||||
",
|
||||
MSZ_FORUM_ROOT,
|
||||
MSZ_FORUM_TYPE_CATEGORY,
|
||||
forum_perms_get_user_sql(MSZ_FORUM_PERMS_GENERAL, '`forum_id`'),
|
||||
MSZ_FORUM_PERM_SET_READ
|
||||
MSZ_FORUM_TYPE_CATEGORY
|
||||
));
|
||||
$getRootForumCount->bindValue('perm_user_id_user', $userId);
|
||||
$getRootForumCount->bindValue('perm_user_id_role', $userId);
|
||||
$categories[0]['forum_children'] = (int)($getRootForumCount->execute() ? $getRootForumCount->fetchColumn() : 0);
|
||||
|
||||
foreach ($categories as $key => $category) {
|
||||
$categories[$key]['forum_permissions'] = $perms = forum_perms_get_user($category['forum_id'], $userId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
|
||||
if (!perms_check($perms, MSZ_FORUM_PERM_SET_READ)) {
|
||||
unset($categories[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$categories[$key] = array_merge(
|
||||
$category,
|
||||
['forum_unread' => forum_topics_unread($category['forum_id'], $userId)],
|
||||
|
@ -172,27 +168,20 @@ function forum_get_breadcrumbs(
|
|||
array $indexLink = ['Forums' => '/forum/']
|
||||
): array {
|
||||
$breadcrumbs = [];
|
||||
$getBreadcrumbs = db_prepare('
|
||||
WITH RECURSIVE breadcrumbs(forum_id, forum_name, forum_parent, forum_type) as (
|
||||
SELECT c.`forum_id`, c.`forum_name`, c.`forum_parent`, c.`forum_type`
|
||||
FROM `msz_forum_categories` as c
|
||||
WHERE `forum_id` = :forum_id
|
||||
UNION ALL
|
||||
SELECT p.`forum_id`, p.`forum_name`, p.`forum_parent`, p.`forum_type`
|
||||
FROM `msz_forum_categories` as p
|
||||
INNER JOIN breadcrumbs
|
||||
ON p.`forum_id` = breadcrumbs.forum_parent
|
||||
)
|
||||
SELECT * FROM breadcrumbs
|
||||
$getBreadcrumb = db_prepare('
|
||||
SELECT `forum_id`, `forum_name`, `forum_type`, `forum_parent`
|
||||
FROM `msz_forum_categories`
|
||||
WHERE `forum_id` = :forum_id
|
||||
');
|
||||
$getBreadcrumbs->bindValue('forum_id', $forumId);
|
||||
$breadcrumbsDb = db_fetch_all($getBreadcrumbs);
|
||||
|
||||
if (!$breadcrumbsDb) {
|
||||
return [$indexLink];
|
||||
}
|
||||
while($forumId > 0) {
|
||||
$getBreadcrumb->bindValue('forum_id', $forumId);
|
||||
$breadcrumb = db_fetch($getBreadcrumb);
|
||||
|
||||
if(empty($breadcrumb)) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($breadcrumbsDb as $breadcrumb) {
|
||||
$breadcrumbs[$breadcrumb['forum_name']] = sprintf(
|
||||
$breadcrumb['forum_parent'] === MSZ_FORUM_ROOT
|
||||
&& $breadcrumb['forum_type'] === MSZ_FORUM_TYPE_CATEGORY
|
||||
|
@ -200,6 +189,7 @@ function forum_get_breadcrumbs(
|
|||
: $linkFormat,
|
||||
$breadcrumb['forum_id']
|
||||
);
|
||||
$forumId = $breadcrumb['forum_parent'];
|
||||
}
|
||||
|
||||
return array_reverse($breadcrumbs + $indexLink);
|
||||
|
@ -208,27 +198,24 @@ function forum_get_breadcrumbs(
|
|||
function forum_get_colour(int $forumId): int
|
||||
{
|
||||
$getColours = db_prepare('
|
||||
WITH RECURSIVE breadcrumbs(forum_id, forum_parent, forum_colour) as (
|
||||
SELECT c.`forum_id`, c.`forum_parent`, c.`forum_colour`
|
||||
FROM `msz_forum_categories` as c
|
||||
WHERE `forum_id` = :forum_id
|
||||
UNION ALL
|
||||
SELECT p.`forum_id`, p.`forum_parent`, p.`forum_colour`
|
||||
FROM `msz_forum_categories` as p
|
||||
INNER JOIN breadcrumbs
|
||||
ON p.`forum_id` = breadcrumbs.forum_parent
|
||||
)
|
||||
SELECT * FROM breadcrumbs
|
||||
SELECT `forum_id`, `forum_parent`, `forum_colour`
|
||||
FROM `msz_forum_categories`
|
||||
WHERE `forum_id` = :forum_id
|
||||
');
|
||||
$getColours->bindValue('forum_id', $forumId);
|
||||
$colours = db_fetch_all($getColours);
|
||||
|
||||
if ($colours) {
|
||||
foreach ($colours as $colour) {
|
||||
if ($colour['forum_colour'] !== null) {
|
||||
return $colour['forum_colour'];
|
||||
}
|
||||
while($forumId > 0) {
|
||||
$getColours->bindValue('forum_id', $forumId);
|
||||
$colourInfo = db_fetch($getColours);
|
||||
|
||||
if(empty($colourInfo)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!empty($colourInfo['forum_colour'])) {
|
||||
return $colourInfo['forum_colour'];
|
||||
}
|
||||
|
||||
$forumId = $colourInfo['forum_parent'];
|
||||
}
|
||||
|
||||
return colour_none();
|
||||
|
@ -247,6 +234,28 @@ function forum_increment_clicks(int $forumId): void
|
|||
$incrementLinkClicks->execute();
|
||||
}
|
||||
|
||||
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 = db_prepare('
|
||||
SELECT `forum_parent`
|
||||
FROM `msz_forum_categories`
|
||||
WHERE `forum_id` = :forum_id
|
||||
');
|
||||
$getParent->bindValue('forum_id', $forumId);
|
||||
|
||||
return (int)($getParent->execute() ? $getParent->fetchColumn() : 0);
|
||||
}
|
||||
|
||||
function forum_get_child_ids(int $forumId): array
|
||||
{
|
||||
if ($forumId < 1) {
|
||||
|
@ -290,29 +299,24 @@ function forum_topics_unread(int $forumId, int $userId): int
|
|||
$memoized[$memoId] += forum_topics_unread($child, $userId);
|
||||
}
|
||||
|
||||
$countUnread = db_prepare(sprintf(
|
||||
'
|
||||
if (forum_perms_check_user(MSZ_FORUM_PERMS_GENERAL, $forumId, $userId, MSZ_FORUM_PERM_SET_READ)) {
|
||||
$countUnread = db_prepare('
|
||||
SELECT COUNT(ti.`topic_id`)
|
||||
FROM `msz_forum_topics` AS ti
|
||||
LEFT JOIN `msz_forum_topics_track` AS tt
|
||||
ON tt.`topic_id` = ti.`topic_id` AND tt.`user_id` = :user_id
|
||||
WHERE ti.`forum_id` = :forum_id
|
||||
AND ((%s) & %d) > 0
|
||||
AND ti.`topic_deleted` IS NULL
|
||||
AND ti.`topic_bumped` >= NOW() - INTERVAL 1 MONTH
|
||||
AND (
|
||||
tt.`track_last_read` IS NULL
|
||||
OR tt.`track_last_read` < ti.`topic_bumped`
|
||||
)
|
||||
',
|
||||
forum_perms_get_user_sql(MSZ_FORUM_PERMS_GENERAL, 'ti.`forum_id`'),
|
||||
MSZ_FORUM_PERM_SET_READ
|
||||
));
|
||||
$countUnread->bindValue('forum_id', $forumId);
|
||||
$countUnread->bindValue('user_id', $userId);
|
||||
$countUnread->bindValue('perm_user_id_user', $userId);
|
||||
$countUnread->bindValue('perm_user_id_role', $userId);
|
||||
$memoized[$memoId] += (int)($countUnread->execute() ? $countUnread->fetchColumn() : 0);
|
||||
');
|
||||
$countUnread->bindValue('forum_id', $forumId);
|
||||
$countUnread->bindValue('user_id', $userId);
|
||||
$memoized[$memoId] += (int)($countUnread->execute() ? $countUnread->fetchColumn() : 0);
|
||||
}
|
||||
|
||||
return $memoized[$memoId];
|
||||
}
|
||||
|
@ -330,34 +334,31 @@ function forum_latest_post(int $forumId, int $userId): array
|
|||
return $memoized[$memoId];
|
||||
}
|
||||
|
||||
$getLastPost = db_prepare(sprintf(
|
||||
'
|
||||
SELECT
|
||||
p.`post_id` AS `recent_post_id`, t.`topic_id` AS `recent_topic_id`,
|
||||
t.`topic_title` AS `recent_topic_title`, t.`topic_bumped` AS `recent_topic_bumped`,
|
||||
p.`post_created` AS `recent_post_created`,
|
||||
u.`user_id` AS `recent_post_user_id`,
|
||||
u.`username` AS `recent_post_username`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) AS `recent_post_user_colour`,
|
||||
UNIX_TIMESTAMP(p.`post_created`) AS `post_created_unix`
|
||||
FROM `msz_forum_posts` AS p
|
||||
LEFT JOIN `msz_forum_topics` AS t
|
||||
ON t.`topic_id` = p.`topic_id`
|
||||
LEFT JOIN `msz_users` AS u
|
||||
ON u.`user_id` = p.`user_id`
|
||||
LEFT JOIN `msz_roles` AS r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
WHERE p.`forum_id` = :forum_id
|
||||
AND p.`post_deleted` IS NULL
|
||||
AND ((%s) & %d) > 0
|
||||
ORDER BY p.`post_id` DESC
|
||||
',
|
||||
forum_perms_get_user_sql(MSZ_FORUM_PERMS_GENERAL, 'p.`forum_id`'),
|
||||
MSZ_FORUM_PERM_SET_READ
|
||||
));
|
||||
if (!forum_perms_check_user(MSZ_FORUM_PERMS_GENERAL, $forumId, $userId, MSZ_FORUM_PERM_SET_READ)) {
|
||||
return $memoized[$memoId] = [];
|
||||
}
|
||||
|
||||
$getLastPost = db_prepare('
|
||||
SELECT
|
||||
p.`post_id` AS `recent_post_id`, t.`topic_id` AS `recent_topic_id`,
|
||||
t.`topic_title` AS `recent_topic_title`, t.`topic_bumped` AS `recent_topic_bumped`,
|
||||
p.`post_created` AS `recent_post_created`,
|
||||
u.`user_id` AS `recent_post_user_id`,
|
||||
u.`username` AS `recent_post_username`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) AS `recent_post_user_colour`,
|
||||
UNIX_TIMESTAMP(p.`post_created`) AS `post_created_unix`
|
||||
FROM `msz_forum_posts` AS p
|
||||
LEFT JOIN `msz_forum_topics` AS t
|
||||
ON t.`topic_id` = p.`topic_id`
|
||||
LEFT JOIN `msz_users` AS u
|
||||
ON u.`user_id` = p.`user_id`
|
||||
LEFT JOIN `msz_roles` AS r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
WHERE p.`forum_id` = :forum_id
|
||||
AND p.`post_deleted` IS NULL
|
||||
ORDER BY p.`post_id` DESC
|
||||
');
|
||||
$getLastPost->bindValue('forum_id', $forumId);
|
||||
$getLastPost->bindValue('perm_user_id_user', $userId);
|
||||
$getLastPost->bindValue('perm_user_id_role', $userId);
|
||||
$currentLast = db_fetch($getLastPost);
|
||||
|
||||
$children = forum_get_child_ids($forumId);
|
||||
|
@ -373,7 +374,7 @@ function forum_latest_post(int $forumId, int $userId): array
|
|||
return $memoized[$memoId] = $currentLast;
|
||||
}
|
||||
|
||||
function forum_get_children(int $parentId, int $userId, bool $showDeleted = false): array
|
||||
function forum_get_children(int $parentId, int $userId): array
|
||||
{
|
||||
$getListing = db_prepare(sprintf(
|
||||
'
|
||||
|
@ -381,8 +382,7 @@ function forum_get_children(int $parentId, int $userId, bool $showDeleted = fals
|
|||
:user_id AS `target_user_id`,
|
||||
f.`forum_id`, f.`forum_name`, f.`forum_description`, f.`forum_type`,
|
||||
f.`forum_link`, f.`forum_link_clicks`, f.`forum_archived`, f.`forum_colour`,
|
||||
f.`forum_count_topics`, f.`forum_count_posts`,
|
||||
(%3$s) AS `forum_permissions`
|
||||
f.`forum_count_topics`, f.`forum_count_posts`
|
||||
FROM `msz_forum_categories` AS f
|
||||
WHERE f.`forum_parent` = :parent_id
|
||||
AND f.`forum_hidden` = 0
|
||||
|
@ -391,25 +391,25 @@ function forum_get_children(int $parentId, int $userId, bool $showDeleted = fals
|
|||
OR f.`forum_parent` != %1$d
|
||||
)
|
||||
GROUP BY f.`forum_id`
|
||||
HAVING (`forum_permissions` & %4$d) > 0
|
||||
ORDER BY f.`forum_order`
|
||||
',
|
||||
MSZ_FORUM_ROOT,
|
||||
MSZ_FORUM_TYPE_CATEGORY,
|
||||
forum_perms_get_user_sql(MSZ_FORUM_PERMS_GENERAL, 'f.`forum_id`'),
|
||||
MSZ_FORUM_PERM_SET_READ,
|
||||
$showDeleted ? '' : 'AND `topic_deleted` IS NULL',
|
||||
$showDeleted ? '' : 'AND `post_deleted` IS NULL'
|
||||
MSZ_FORUM_TYPE_CATEGORY
|
||||
));
|
||||
|
||||
$getListing->bindValue('user_id', $userId);
|
||||
$getListing->bindValue('perm_user_id_user', $userId);
|
||||
$getListing->bindValue('perm_user_id_role', $userId);
|
||||
$getListing->bindValue('parent_id', $parentId);
|
||||
|
||||
$listing = db_fetch_all($getListing);
|
||||
|
||||
foreach ($listing as $key => $forum) {
|
||||
$listing[$key]['forum_permissions'] = $perms = forum_perms_get_user($forum['forum_id'], $userId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
|
||||
if (!perms_check($perms, MSZ_FORUM_PERM_SET_READ)) {
|
||||
unset($listing[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$listing[$key] = array_merge(
|
||||
$forum,
|
||||
['forum_unread' => forum_topics_unread($forum['forum_id'], $userId)],
|
||||
|
@ -454,13 +454,10 @@ function forum_mark_read(?int $forumId, int $userId): void
|
|||
AND t.`topic_bumped` >= NOW() - INTERVAL 1 MONTH
|
||||
%1$s
|
||||
GROUP BY t.`topic_id`
|
||||
HAVING ((%2$s) & %3$d) > 0
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`track_last_read` = NOW()
|
||||
',
|
||||
$entireForum ? '' : 'AND t.`forum_id` = :forum',
|
||||
forum_perms_get_user_sql(MSZ_FORUM_PERMS_GENERAL, 't.`forum_id`', 'u.`user_id`', 'u.`user_id`'),
|
||||
MSZ_FORUM_PERM_SET_READ
|
||||
$entireForum ? '' : 'AND t.`forum_id` = :forum'
|
||||
));
|
||||
$doMark->bindValue('user', $userId);
|
||||
|
||||
|
|
|
@ -5,106 +5,109 @@ define('MSZ_FORUM_PERM_MODES', [
|
|||
MSZ_FORUM_PERMS_GENERAL,
|
||||
]);
|
||||
|
||||
function forum_perms_get_keys(): array
|
||||
function forum_perms_get_user(?int $forum, int $user): array
|
||||
{
|
||||
$perms = [];
|
||||
$perms = perms_get_blank(MSZ_FORUM_PERM_MODES);
|
||||
|
||||
foreach (MSZ_FORUM_PERM_MODES as $mode) {
|
||||
foreach (MSZ_PERM_SETS as $set) {
|
||||
$perms[] = perms_get_key($mode, $set);
|
||||
}
|
||||
if ($user < 1 || $forum < 0) {
|
||||
return $perms;
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
static $memo = [];
|
||||
$memoId = "{$forum}-{$user}";
|
||||
|
||||
function forum_perms_create(): array
|
||||
{
|
||||
$perms = [];
|
||||
|
||||
foreach (forum_perms_get_keys() as $key) {
|
||||
$perms[$key] = 0;
|
||||
if (array_key_exists($memoId, $memo)) {
|
||||
return $memo[$memoId];
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
if ($forum > 0) {
|
||||
$perms = forum_perms_get_user(
|
||||
forum_get_parent_id($forum),
|
||||
$user
|
||||
);
|
||||
}
|
||||
|
||||
function forum_perms_get_user_sql(
|
||||
string $prefix,
|
||||
string $forum_id_param = ':perm_forum_id',
|
||||
string $user_id_user_param = ':perm_user_id_user',
|
||||
string $user_id_role_param = ':perm_user_id_role'
|
||||
): string {
|
||||
return sprintf(
|
||||
$getPerms = db_prepare(sprintf(
|
||||
'
|
||||
SELECT BIT_OR(`%1$s_perms`)
|
||||
FROM `msz_forum_permissions_view`
|
||||
WHERE (`forum_id` = %2$s OR `forum_id` IS NULL)
|
||||
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` = %3$s AND `role_id` IS NULL)
|
||||
(`user_id` = :user_id_1 AND `role_id` IS NULL)
|
||||
OR (
|
||||
`user_id` IS NULL
|
||||
AND `role_id` IN (
|
||||
SELECT `role_id`
|
||||
FROM `msz_user_roles`
|
||||
WHERE `user_id` = %4$s
|
||||
WHERE `user_id` = :user_id_2
|
||||
)
|
||||
)
|
||||
)
|
||||
',
|
||||
$prefix,
|
||||
$forum_id_param,
|
||||
$user_id_user_param,
|
||||
$user_id_role_param
|
||||
);
|
||||
perms_get_select(MSZ_FORUM_PERM_MODES)
|
||||
));
|
||||
$getPerms->bindValue('forum_id', $forum);
|
||||
$getPerms->bindValue('user_id_1', $user);
|
||||
$getPerms->bindValue('user_id_2', $user);
|
||||
|
||||
return $memo[$memoId] = array_bit_or($perms, db_fetch($getPerms));
|
||||
}
|
||||
|
||||
function forum_perms_get_user(string $prefix, int $forum, int $user): int
|
||||
function forum_perms_get_role(?int $forum, int $role): array
|
||||
{
|
||||
if (!in_array($prefix, MSZ_FORUM_PERM_MODES) || $user < 0) {
|
||||
return 0;
|
||||
$perms = perms_get_blank(MSZ_FORUM_PERM_MODES);
|
||||
|
||||
if ($role < 1 || $forum < 0) {
|
||||
return $perms;
|
||||
}
|
||||
|
||||
$getPerms = db_prepare(forum_perms_get_user_sql($prefix));
|
||||
$getPerms->bindValue('perm_forum_id', $forum);
|
||||
$getPerms->bindValue('perm_user_id_user', $user);
|
||||
$getPerms->bindValue('perm_user_id_role', $user);
|
||||
return $getPerms->execute() ? (int)$getPerms->fetchColumn() : 0;
|
||||
}
|
||||
static $memo = [];
|
||||
$memoId = "{$forum}-{$role}";
|
||||
|
||||
function forum_perms_get_role(string $prefix, int $forum, int $role): int
|
||||
{
|
||||
if (!in_array($prefix, MSZ_FORUM_PERM_MODES) || $role < 1) {
|
||||
return 0;
|
||||
if (array_key_exists($memoId, $memo)) {
|
||||
return $memo[$memoId];
|
||||
}
|
||||
|
||||
$getPerms = db_prepare("
|
||||
SELECT BIT_OR(`{$prefix}_perms`)
|
||||
FROM `msz_forum_permissions_view`
|
||||
WHERE (`forum_id` = :forum_id OR `forum_id` IS NULL)
|
||||
AND `role_id` = :role_id
|
||||
AND `user_id` IS NULL
|
||||
");
|
||||
if ($forum > 0) {
|
||||
$perms = forum_perms_get_role(
|
||||
forum_get_parent_id($forum),
|
||||
$role
|
||||
);
|
||||
}
|
||||
|
||||
$getPerms = db_prepare(sprintf(
|
||||
'
|
||||
SELECT %s
|
||||
FROM `msz_forum_permissions`
|
||||
WHERE (`forum_id` = :forum_id OR `forum_id` IS NULL)
|
||||
AND `role_id` = :role_id
|
||||
AND `user_id` IS NULL
|
||||
',
|
||||
perms_get_select(MSZ_FORUM_PERM_MODES)
|
||||
));
|
||||
$getPerms->bindValue('forum_id', $forum);
|
||||
$getPerms->bindValue('role_id', $role);
|
||||
return $getPerms->execute() ? (int)$getPerms->fetchColumn() : 0;
|
||||
|
||||
return $memo[$memoId] = array_bit_or($perms, db_fetch($getPerms));
|
||||
}
|
||||
|
||||
function forum_perms_get_user_raw(?int $forum, int $user): array
|
||||
{
|
||||
if ($user < 1) {
|
||||
return forum_perms_create();
|
||||
return perms_create(MSZ_FORUM_PERM_MODES);
|
||||
}
|
||||
|
||||
$getPerms = db_prepare(sprintf('
|
||||
SELECT
|
||||
`' . implode('`, `', forum_perms_get_keys()) . '`
|
||||
FROM `msz_forum_permissions`
|
||||
WHERE `forum_id` %s
|
||||
AND `user_id` = :user_id
|
||||
AND `role_id` IS NULL
|
||||
', $forum === null ? 'IS NULL' : '= :forum_id'));
|
||||
$getPerms = db_prepare(sprintf(
|
||||
'
|
||||
SELECT `%s`
|
||||
FROM `msz_forum_permissions`
|
||||
WHERE `forum_id` %s
|
||||
AND `user_id` = :user_id
|
||||
AND `role_id` IS NULL
|
||||
',
|
||||
implode('`, `', perms_get_keys(MSZ_FORUM_PERM_MODES)),
|
||||
$forum === null ? 'IS NULL' : '= :forum_id'
|
||||
));
|
||||
|
||||
if ($forum !== null) {
|
||||
$getPerms->bindValue('forum_id', $forum);
|
||||
|
@ -114,7 +117,7 @@ function forum_perms_get_user_raw(?int $forum, int $user): array
|
|||
$perms = db_fetch($getPerms);
|
||||
|
||||
if (empty($perms)) {
|
||||
return forum_perms_create();
|
||||
return perms_create(MSZ_FORUM_PERM_MODES);
|
||||
}
|
||||
|
||||
return $perms;
|
||||
|
@ -123,18 +126,18 @@ function forum_perms_get_user_raw(?int $forum, int $user): array
|
|||
function forum_perms_get_role_raw(?int $forum, ?int $role): array
|
||||
{
|
||||
if ($role < 1 && $role !== null) {
|
||||
return forum_perms_create();
|
||||
return perms_create(MSZ_FORUM_PERM_MODES);
|
||||
}
|
||||
|
||||
$getPerms = db_prepare(sprintf(
|
||||
'
|
||||
SELECT
|
||||
`' . implode('`, `', forum_perms_get_keys()) . '`
|
||||
SELECT `%s`
|
||||
FROM `msz_forum_permissions`
|
||||
WHERE `forum_id` %s
|
||||
AND `user_id` IS NULL
|
||||
AND `role_id` %s
|
||||
',
|
||||
implode('`, `', perms_get_keys(MSZ_FORUM_PERM_MODES)),
|
||||
$forum === null ? 'IS NULL' : '= :forum_id',
|
||||
$role === null ? 'IS NULL' : '= :role_id'
|
||||
));
|
||||
|
@ -150,8 +153,13 @@ function forum_perms_get_role_raw(?int $forum, ?int $role): array
|
|||
$perms = db_fetch($getPerms);
|
||||
|
||||
if (empty($perms)) {
|
||||
return forum_perms_create();
|
||||
return perms_create(MSZ_FORUM_PERM_MODES);
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
|
||||
function forum_perms_check_user(string $prefix, ?int $forumId, ?int $userId, int $perm): bool
|
||||
{
|
||||
return $userId > 0 && perms_check(forum_perms_get_user($forumId, $userId)[$prefix] ?? 0, $perm);
|
||||
}
|
||||
|
|
|
@ -64,24 +64,26 @@ function forum_post_find(int $postId, int $userId): array
|
|||
'
|
||||
SELECT
|
||||
p.`post_id`, p.`topic_id`,
|
||||
((%s) & %d) as `can_view_deleted`,
|
||||
(
|
||||
SELECT COUNT(`post_id`)
|
||||
FROM `msz_forum_posts`
|
||||
WHERE `topic_id` = p.`topic_id`
|
||||
AND `post_id` < p.`post_id`
|
||||
AND (`can_view_deleted` OR `post_deleted` IS NULL)
|
||||
AND `post_deleted` IS NULL
|
||||
ORDER BY `post_id`
|
||||
) as `preceeding_post_count`
|
||||
) as `preceeding_post_count`,
|
||||
(
|
||||
SELECT COUNT(`post_id`)
|
||||
FROM `msz_forum_posts`
|
||||
WHERE `topic_id` = p.`topic_id`
|
||||
AND `post_id` < p.`post_id`
|
||||
AND `post_deleted` IS NOT NULL
|
||||
ORDER BY `post_id`
|
||||
) as `preceeding_post_deleted_count`
|
||||
FROM `msz_forum_posts` AS p
|
||||
WHERE p.`post_id` = :post_id
|
||||
',
|
||||
forum_perms_get_user_sql(MSZ_FORUM_PERMS_GENERAL, 'p.`forum_id`'),
|
||||
MSZ_FORUM_PERM_DELETE_ANY_POST
|
||||
));
|
||||
'));
|
||||
$getPostInfo->bindValue('post_id', $postId);
|
||||
$getPostInfo->bindValue('perm_user_id_user', $userId);
|
||||
$getPostInfo->bindValue('perm_user_id_role', $userId);
|
||||
return db_fetch($getPostInfo);
|
||||
}
|
||||
|
||||
|
@ -232,7 +234,7 @@ function forum_post_can_delete($postId, ?int $userId = null): int
|
|||
}
|
||||
|
||||
$isSystemReq = $userId === null;
|
||||
$perms = $isSystemReq ? 0 : forum_perms_get_user(MSZ_FORUM_PERMS_GENERAL, $post['forum_id'], $userId);
|
||||
$perms = $isSystemReq ? 0 : forum_perms_get_user($post['forum_id'], $userId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
$canDeleteAny = $isSystemReq ? true : perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST);
|
||||
$canViewPost = $isSystemReq ? true : perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM);
|
||||
$postIsDeleted = !empty($post['post_deleted']);
|
||||
|
|
|
@ -451,7 +451,7 @@ function forum_topic_can_delete($topicId, ?int $userId = null): int
|
|||
}
|
||||
|
||||
$isSystemReq = $userId === null;
|
||||
$perms = $isSystemReq ? 0 : forum_perms_get_user(MSZ_FORUM_PERMS_GENERAL, $topic['forum_id'], $userId);
|
||||
$perms = $isSystemReq ? 0 : forum_perms_get_user($topic['forum_id'], $userId)[MSZ_FORUM_PERMS_GENERAL];
|
||||
$canDeleteAny = $isSystemReq ? true : perms_check($perms, MSZ_FORUM_PERM_DELETE_ANY_POST);
|
||||
$canViewPost = $isSystemReq ? true : perms_check($perms, MSZ_FORUM_PERM_VIEW_FORUM);
|
||||
$postIsDeleted = !empty($topic['topic_deleted']);
|
||||
|
|
|
@ -19,15 +19,11 @@ function array_apply(array $array, callable $func): array
|
|||
return $array;
|
||||
}
|
||||
|
||||
if (!function_exists('array_key_first')) {
|
||||
// https://secure.php.net/manual/en/function.array-key-first.php#123301
|
||||
function array_key_first(array $array)
|
||||
{
|
||||
if (count($array)) {
|
||||
reset($array);
|
||||
return key($array);
|
||||
}
|
||||
|
||||
return null;
|
||||
function array_bit_or(array $array1, array $array2): array
|
||||
{
|
||||
foreach ($array1 as $key => $value) {
|
||||
$array1[$key] |= $array2[$key] ?? 0;
|
||||
}
|
||||
|
||||
return $array1;
|
||||
}
|
||||
|
|
|
@ -14,32 +14,23 @@ define('MSZ_PERM_MODES', [
|
|||
define('MSZ_PERMS_ALLOW', 'allow');
|
||||
define('MSZ_PERMS_DENY', 'deny');
|
||||
|
||||
define('MSZ_PERM_SETS', [
|
||||
MSZ_PERMS_ALLOW, MSZ_PERMS_DENY,
|
||||
]);
|
||||
|
||||
function perms_get_keys(): array
|
||||
function perms_get_keys(array $modes = MSZ_PERM_MODES): array
|
||||
{
|
||||
$perms = [];
|
||||
|
||||
foreach (MSZ_PERM_MODES as $mode) {
|
||||
foreach (MSZ_PERM_SETS as $set) {
|
||||
$perms[] = perms_get_key($mode, $set);
|
||||
}
|
||||
$perms[] = [
|
||||
perms_get_key($mode, MSZ_PERMS_ALLOW),
|
||||
perms_get_key($mode, MSZ_PERMS_DENY),
|
||||
];
|
||||
}
|
||||
|
||||
return $perms;
|
||||
}
|
||||
|
||||
function perms_create(): array
|
||||
function perms_create(array $modes = MSZ_PERM_MODES): array
|
||||
{
|
||||
$perms = [];
|
||||
|
||||
foreach (perms_get_keys() as $key) {
|
||||
$perms[$key] = 0;
|
||||
}
|
||||
|
||||
return $perms;
|
||||
return array_fill_keys(perms_get_keys($modes), 0);
|
||||
}
|
||||
|
||||
function perms_get_key(string $prefix, string $suffix): string
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
{{ container_title('<i class="fas fa-comment-slash fa-fw"></i> Forums') }}
|
||||
|
||||
<div class="container__content">
|
||||
<p>There are no forums yet, check back later!</p>
|
||||
<p>There are currently no visible forums.</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
Loading…
Add table
Reference in a new issue