Skip to content

Commit

Permalink
Move forum attributes to class to fix redeclare issues
Browse files Browse the repository at this point in the history
Add check for Tags extension before retrieving scoped permissions

Co-Authored-By: Robert Korulczyk <[email protected]>
  • Loading branch information
clarkwinkelmann and rob006 committed Aug 17, 2022
1 parent 92fbaa9 commit b1082b4
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 43 deletions.
44 changes: 1 addition & 43 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,6 @@

use Flarum\Api\Serializer\ForumSerializer;
use Flarum\Extend;
use Flarum\Extension\ExtensionManager;
use Flarum\User\User;

function hasGlobalOrScopedPermission(User $actor, string $permission): bool
{
if ($actor->hasPermission($permission)) {
return true;
}

// Same logic as Tag::scopeWhereHasPermission
// Benefits of re-implementing: no need to check Tags is enabled + extension loading order doesn't matter
// Downside: if you disable Tags while scopes existed, those will still be read
foreach ($actor->getPermissions() as $thisPermission) {
if (substr($thisPermission, 0, 3) === 'tag' && strpos($thisPermission, $permission) !== false) {
return true;
}
}

return false;
}

return [
(new Extend\Frontend('forum'))
Expand All @@ -36,27 +16,5 @@ function hasGlobalOrScopedPermission(User $actor, string $permission): bool
new Extend\Locales(__DIR__ . '/resources/locale'),

(new Extend\ApiSerializer(ForumSerializer::class))
->attributes(function (ForumSerializer $serializer) {
/**
* @var ExtensionManager $manager
*/
$manager = resolve(ExtensionManager::class);

return [
'massControls' => $serializer->getActor()->hasPermission('mass-actions.controls'),
'canHideDiscussionsSometime' => hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.hide'),
'canDeleteDiscussionsSometime' => hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.delete'),
'canLockDiscussionsSometime' => hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.lock')
&& $manager->isEnabled('flarum-lock'),
'canStickyDiscussionsSometime' => hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.sticky')
&& $manager->isEnabled('flarum-sticky'),
// The tag edit policy is split between moderator permission and self-edit permission
// We will only enable the mass control if self tag edit was set to "indefinitely"
'canTagDiscussionsSometime' => (
hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.tag')
|| resolve('flarum.settings')->get('allow_tag_change') === '-1'
)
&& $manager->isEnabled('flarum-tags'),
];
}),
->attributes(ForumAttributes::class),
];
59 changes: 59 additions & 0 deletions src/ForumAttributes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace ClarkWinkelmann\MassActions;

use Flarum\Api\Serializer\ForumSerializer;
use Flarum\Extension\ExtensionManager;
use Flarum\User\User;

class ForumAttributes
{
protected $manager;

public function __construct(ExtensionManager $manager)
{
$this->manager = $manager;
}

public function __invoke(ForumSerializer $serializer): array
{
return [
'massControls' => $serializer->getActor()->hasPermission('mass-actions.controls'),
'canHideDiscussionsSometime' => $this->hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.hide'),
'canDeleteDiscussionsSometime' => $this->hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.delete'),
'canLockDiscussionsSometime' => $this->hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.lock')
&& $this->manager->isEnabled('flarum-lock'),
'canStickyDiscussionsSometime' => $this->hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.sticky')
&& $this->manager->isEnabled('flarum-sticky'),
// The tag edit policy is split between moderator permission and self-edit permission
// We will only enable the mass control if self tag edit was set to "indefinitely"
'canTagDiscussionsSometime' => (
$this->hasGlobalOrScopedPermission($serializer->getActor(), 'discussion.tag')
|| resolve('flarum.settings')->get('allow_tag_change') === '-1'
)
&& $this->manager->isEnabled('flarum-tags'),
];
}

protected function hasGlobalOrScopedPermission(User $actor, string $permission): bool
{
if ($actor->hasPermission($permission)) {
return true;
}

// Skip tag permission check below if Tags is disabled, otherwise inactive scoped permissions still in the database would be read
if (!$this->manager->isEnabled('flarum-tags')) {
return false;
}

// Same logic as Tag::scopeWhereHasPermission but without retrieving any tag from the database
// Possible issue: there could be stale scoped permissions still in the database for tag IDs that no longer exist
foreach ($actor->getPermissions() as $thisPermission) {
if (substr($thisPermission, 0, 3) === 'tag' && strpos($thisPermission, $permission) !== false) {
return true;
}
}

return false;
}
}

0 comments on commit b1082b4

Please sign in to comment.