mirror of
https://github.com/flarum/core.git
synced 2025-07-19 07:41:22 +02:00
Overhaul permissions
Get rid of Permissible - too complex and inefficient. Replace with: - a “Locked” trait which works similarly but only evaluates logic on hydrated models. - a “VisibleScope” trait which also works similarly but only scopes queries This is all we need, Permissible is overkill. There is only one instance where we have to duplicate some logic (Discussion::scopeVisiblePosts and Post::allow(‘view’, …)) but it’s barely anything. Haven’t decoupled for now, we can definitely look at doing that later. Permissions table seeder slightly updated. Also did a bit of a query audit, there’s still a lot to be done but it’s much better than it was. Some relatively low-hanging fruit detailed in EloquentPostRepository.
This commit is contained in:
@@ -185,71 +185,78 @@ class CoreServiceProvider extends ServiceProvider
|
||||
$this->extend(
|
||||
new Permission('forum.view'),
|
||||
new Permission('forum.startDiscussion'),
|
||||
new Permission('discussion.rename'),
|
||||
new Permission('discussion.delete'),
|
||||
new Permission('discussion.reply'),
|
||||
new Permission('post.edit'),
|
||||
new Permission('post.delete')
|
||||
new Permission('discussion.editPosts'),
|
||||
new Permission('discussion.deletePosts'),
|
||||
new Permission('discussion.rename'),
|
||||
new Permission('discussion.delete')
|
||||
);
|
||||
|
||||
Forum::grantPermission(function ($grant, $user, $permission) {
|
||||
return $user->hasPermission('forum.'.$permission);
|
||||
Forum::allow('*', function ($forum, $user, $action) {
|
||||
if ($user->hasPermission('forum.'.$action)) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Post::grantPermission(function ($grant, $user, $permission) {
|
||||
return $user->hasPermission('post'.$permission);
|
||||
Post::allow('*', function ($post, $user, $action) {
|
||||
if ($user->hasPermission('post.'.$action)) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Grant view access to a post only if the user can also view the
|
||||
// discussion which the post is in. Also, the if the post is hidden,
|
||||
// the user must have edit permissions too.
|
||||
Post::grantPermission('view', function ($grant) {
|
||||
$grant->whereCan('view', 'discussion');
|
||||
});
|
||||
|
||||
Post::demandPermission('view', function ($demand) {
|
||||
$demand->whereNull('hide_user_id')
|
||||
->orWhereCan('edit');
|
||||
});
|
||||
|
||||
// Allow a user to edit their own post, unless it has been hidden by
|
||||
// someone else.
|
||||
Post::grantPermission('edit', function ($grant, $user) {
|
||||
$grant->where('user_id', $user->id)
|
||||
->where(function ($query) use ($user) {
|
||||
// When fetching a discussion's posts: if the user doesn't have permission
|
||||
// to moderate the discussion, then they can't see posts that have been
|
||||
// hidden by someone other than themself.
|
||||
Discussion::scopeVisiblePosts(function ($query, User $user, Discussion $discussion) {
|
||||
if (! $discussion->can($user, 'editPosts')) {
|
||||
$query->where(function ($query) use ($user) {
|
||||
$query->whereNull('hide_user_id')
|
||||
->orWhere('hide_user_id', $user->id);
|
||||
});
|
||||
// @todo add limitations to time etc. according to a config setting
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
User::grantPermission(function ($grant, $user, $permission) {
|
||||
return $user->hasPermission('user.'.$permission);
|
||||
Post::allow('view', function ($post, $user) {
|
||||
if (! $post->hide_user_id || $post->can($user, 'edit')) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Grant view access to a user if the user can view the forum.
|
||||
User::grantPermission('view', function ($grant, $user) {
|
||||
$grant->whereCan('view', 'forum');
|
||||
// A post is allowed to be edited if the user has permission to moderate
|
||||
// the discussion which it's in, or if they are the author and the post
|
||||
// hasn't been deleted by someone else.
|
||||
Post::allow('edit', function ($post, $user) {
|
||||
if ($post->discussion->can($user, 'editPosts') ||
|
||||
($post->user_id == $user->id && (! $post->hide_user_id || $post->hide_user_id == $user->id))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Allow a user to edit their own account.
|
||||
User::grantPermission(['edit', 'delete'], function ($grant, $user) {
|
||||
$grant->where('id', $user->id);
|
||||
User::allow('*', function ($discussion, $user, $action) {
|
||||
if ($user->hasPermission('user.'.$action)) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Discussion::grantPermission(function ($grant, $user, $permission) {
|
||||
return $user->hasPermission('discussion.'.$permission);
|
||||
User::allow(['edit', 'delete'], function ($user, $actor) {
|
||||
if ($user->id == $actor->id) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Grant view access to a discussion if the user can view the forum.
|
||||
Discussion::grantPermission('view', function ($grant, $user) {
|
||||
$grant->whereCan('view', 'forum');
|
||||
Discussion::allow('*', function ($discussion, $user, $action) {
|
||||
if ($user->hasPermission('discussion.'.$action)) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Allow a user to rename their own discussion.
|
||||
Discussion::grantPermission('rename', function ($grant, $user) {
|
||||
$grant->where('start_user_id', $user->id);
|
||||
// @todo add limitations to time etc. according to a config setting
|
||||
Discussion::allow('rename', function ($discussion, $user) {
|
||||
if ($discussion->start_user_id == $user->id) {
|
||||
return true;
|
||||
// @todo add limitations to time etc. according to a config setting
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user