1
0
mirror of https://github.com/flarum/core.git synced 2025-08-13 20:04:24 +02:00

Compare commits

...

3 Commits

Author SHA1 Message Date
StyleCI Bot
70135459ce Apply fixes from StyleCI 2023-03-26 20:07:37 +00:00
Daniël Klabbers
3c82a887a8 fix: only allow no one if configured, fallback to admin otherwise 2023-03-26 22:07:08 +02:00
Daniël Klabbers
7dcbbf29ab feat(permission): add the no one permission
One thing that has been very frustrating while developing extensions is
that you cannot easily create a feature that you would like to allow
disabling through the permission grid.

This Proof of Concept PR is a question, whether I'm the only one running
into this limitation for Flarum.

It does:

- introduce a fake permission, similar to Guest
- removes the whole permission entry from the db when selected
- restores the permission visually on the frontend

It has to:

- confirm admins also cannot use the permission if selected
- not break v1.x functionality or be moved to v2.0
- appeal to core and community
2023-03-26 10:03:09 +02:00
16 changed files with 69249 additions and 1136 deletions

30362
framework/core/js/dist/admin.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

37513
framework/core/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -52,11 +52,14 @@ export default class PermissionDropdown<CustomAttrs extends IPermissionDropdownA
groupIds = filterByRequiredPermissions(groupIds, this.attrs.permission);
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<Group>('groups', Group.ADMINISTRATOR_ID)!;
if (everyone) {
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' });
} else if (members) {
this.attrs.label = Badge.component({ icon: 'fas fa-user' });
@@ -65,6 +68,17 @@ export default class PermissionDropdown<CustomAttrs extends IPermissionDropdownA
}
if (this.showing) {
if (this.attrs.allowNoOne) {
children.push(
Button.component(
{
icon: no_one ? 'fas fa-check' : true,
onclick: () => this.save([Group.NO_ONE_ID]),
},
[Badge.component({ icon: 'fas fa-user-slash' }), ' ', app.translator.trans('core.admin.permissions_controls.no_one_button')]
)
);
}
if (this.attrs.allowGuest) {
children.push(
Button.component(

View File

@@ -12,6 +12,7 @@ export interface PermissionConfig {
icon: string;
label: Mithril.Children;
allowGuest?: boolean;
allowNoOne?: boolean;
}
export interface PermissionSetting {
@@ -435,6 +436,7 @@ export default class PermissionGrid<CustomAttrs extends IPermissionGridAttrs = I
return PermissionDropdown.component({
permission: item.permission,
allowGuest: item.allowGuest,
allowNoOne: item.allowNoOne,
});
}

View File

@@ -1,6 +1,7 @@
import Model from '../Model';
export default class Group extends Model {
static NO_ONE_ID = '-1';
static ADMINISTRATOR_ID = '1';
static GUEST_ID = '2';
static MEMBER_ID = '3';

View File

@@ -235,6 +235,7 @@ core:
members_button: => core.group.members
signup_closed_button: Closed
signup_open_button: Open
no_one_button: No one
# These translations are used generically in setting fields.
settings:

View File

@@ -9,6 +9,7 @@
namespace Flarum\Api\Controller;
use Flarum\Group\Group;
use Flarum\Group\Permission;
use Flarum\Http\RequestUtil;
use Illuminate\Support\Arr;
@@ -32,6 +33,11 @@ class SetPermissionController implements RequestHandlerInterface
Permission::where('permission', $permission)->delete();
// Permission set to no one.
if (count($groupIds) === 1 && intval($groupIds[0]) === Group::NO_ONE_ID) {
return new EmptyResponse(204);
}
Permission::insert(array_map(function ($groupId) use ($permission) {
return [
'permission' => $permission,

View File

@@ -0,0 +1,29 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Extend;
use Flarum\Extension\Extension;
use Flarum\User\Access\AdminPolicy;
use Illuminate\Contracts\Container\Container;
class Permission implements ExtenderInterface
{
public function extend(Container $container, Extension $extension = null)
{
// TODO: Implement extend() method.
}
public function allowsNoOne(string $permission): self
{
AdminPolicy::allowNoOneOnPermission($permission);
return $this;
}
}

View File

@@ -32,6 +32,11 @@ class Group extends AbstractModel
use EventGeneratorTrait;
use ScopeVisibilityTrait;
/**
* The temporary ID for when no one can do something.
*/
const NO_ONE_ID = -1;
/**
* The ID of the administrator group.
*/

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\User\Access;
use Flarum\User\User;
class AdminPolicy extends AbstractPolicy
{
public static array $allowNoOnePermissions = [];
/**
* @param string|array<string> $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();
}
}
}

View File

@@ -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);
}
/**

View File

@@ -380,10 +380,6 @@ class User extends AbstractModel
*/
public function hasPermission($permission)
{
if ($this->isAdmin()) {
return true;
}
return in_array($permission, $this->getPermissions());
}
@@ -396,10 +392,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;

View File

@@ -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],

2387
yarn.lock

File diff suppressed because it is too large Load Diff