diff --git a/framework/core/js/src/admin/components/PermissionDropdown.tsx b/framework/core/js/src/admin/components/PermissionDropdown.tsx index 6e056e531..0a3c816a2 100644 --- a/framework/core/js/src/admin/components/PermissionDropdown.tsx +++ b/framework/core/js/src/admin/components/PermissionDropdown.tsx @@ -48,16 +48,16 @@ export default class PermissionDropdown) { const children = []; - let groupIds = app.data.permissions[this.attrs.permission] || [Group.NO_ONE_ID]; + let groupIds = app.data.permissions[this.attrs.permission] || []; groupIds = filterByRequiredPermissions(groupIds, this.attrs.permission); - const no_one = groupIds.includes(Group.NO_ONE_ID); + const no_one = groupIds.length === 0; const everyone = groupIds.includes(Group.GUEST_ID); const members = groupIds.includes(Group.MEMBER_ID); const adminGroup = app.store.getById('groups', Group.ADMINISTRATOR_ID)!; - if (no_one) { + if (this.attrs.allowNoOne && no_one) { this.attrs.label = Badge.component({ icon: 'fas fa-user-slash' }); } else if (everyone) { this.attrs.label = Badge.component({ icon: 'fas fa-globe' }); @@ -74,7 +74,6 @@ export default class PermissionDropdown this.save([Group.NO_ONE_ID]), - disabled: this.isGroupDisabled(Group.NO_ONE_ID), }, [Badge.component({ icon: 'fas fa-user-slash' }), ' ', app.translator.trans('core.admin.permissions_controls.no_one_button')] ) diff --git a/framework/core/src/Extend/Permission.php b/framework/core/src/Extend/Permission.php new file mode 100644 index 000000000..394bb6398 --- /dev/null +++ b/framework/core/src/Extend/Permission.php @@ -0,0 +1,22 @@ + $permissions + * @return void + */ + public static function allowNoOneOnPermission($permissions) + { + self::$allowNoOnePermissions[] = array_merge( + static::$allowNoOnePermissions, + (array) $permissions + ); + } + + /** + * @param User $actor + * @param string $ability + * @return bool|null + */ + public function can(User $actor, $ability) + { + if (! in_array($ability, static::$allowNoOnePermissions) + && $actor->isAdmin()) { + return $this->forceAllow(); + } + } +} diff --git a/framework/core/src/User/Access/Gate.php b/framework/core/src/User/Access/Gate.php index e8eaab1a3..f9bf6d7c7 100644 --- a/framework/core/src/User/Access/Gate.php +++ b/framework/core/src/User/Access/Gate.php @@ -87,11 +87,7 @@ class Gate // If no policy covered this permission query, we will only grant // the permission if the actor's groups have it. Otherwise, we will // not allow the user to perform this action. - if ($actor->isAdmin() || $actor->hasPermission($ability)) { - return true; - } - - return false; + return $actor->hasPermission($ability); } /** diff --git a/framework/core/src/User/User.php b/framework/core/src/User/User.php index 4231328b6..c87665850 100644 --- a/framework/core/src/User/User.php +++ b/framework/core/src/User/User.php @@ -380,9 +380,7 @@ class User extends AbstractModel */ public function hasPermission($permission) { - if ($this->isAdmin()) { - return true; - } + return in_array($permission, $this->getPermissions()); } @@ -396,10 +394,6 @@ class User extends AbstractModel */ public function hasPermissionLike($match) { - if ($this->isAdmin()) { - return true; - } - foreach ($this->getPermissions() as $permission) { if (substr($permission, -strlen($match)) === $match) { return true; diff --git a/framework/core/src/User/UserServiceProvider.php b/framework/core/src/User/UserServiceProvider.php index abe37efb3..f9eb3bd83 100644 --- a/framework/core/src/User/UserServiceProvider.php +++ b/framework/core/src/User/UserServiceProvider.php @@ -20,6 +20,7 @@ use Flarum\Http\AccessToken; use Flarum\Post\Access\PostPolicy; use Flarum\Post\Post; use Flarum\Settings\SettingsRepositoryInterface; +use Flarum\User\Access\AdminPolicy; use Flarum\User\Access\ScopeUserVisibility; use Flarum\User\DisplayName\DriverInterface; use Flarum\User\DisplayName\UsernameDriver; @@ -49,7 +50,7 @@ class UserServiceProvider extends AbstractServiceProvider $this->container->singleton('flarum.policies', function () { return [ - Access\AbstractPolicy::GLOBAL => [], + Access\AbstractPolicy::GLOBAL => [AdminPolicy::class], AccessToken::class => [AccessTokenPolicy::class], Discussion::class => [DiscussionPolicy::class], Group::class => [GroupPolicy::class],