mirror of
https://github.com/flarum/core.git
synced 2025-07-20 00:01:17 +02:00
User Extender (prepareGroups functionality) (#2110)
This commit is contained in:
committed by
GitHub
parent
b89ccaf83c
commit
c10ebea00c
@@ -12,6 +12,7 @@ namespace Flarum\Event;
|
|||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated beta 13, remove in beta 14. Use the User extender instead.
|
||||||
* The `PrepareUserGroups` event.
|
* The `PrepareUserGroups` event.
|
||||||
*/
|
*/
|
||||||
class PrepareUserGroups
|
class PrepareUserGroups
|
||||||
|
@@ -15,9 +15,10 @@ use Illuminate\Contracts\Container\Container;
|
|||||||
class User implements ExtenderInterface
|
class User implements ExtenderInterface
|
||||||
{
|
{
|
||||||
private $displayNameDrivers = [];
|
private $displayNameDrivers = [];
|
||||||
|
private $groupProcessors = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a mail driver.
|
* Add a display name driver.
|
||||||
*
|
*
|
||||||
* @param string $identifier Identifier for display name driver. E.g. 'username' for UserNameDriver
|
* @param string $identifier Identifier for display name driver. E.g. 'username' for UserNameDriver
|
||||||
* @param string $driver ::class attribute of driver class, which must implement Flarum\User\DisplayName\DriverInterface
|
* @param string $driver ::class attribute of driver class, which must implement Flarum\User\DisplayName\DriverInterface
|
||||||
@@ -29,10 +30,35 @@ class User implements ExtenderInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically process a user's list of groups when calculating permissions.
|
||||||
|
* This can be used to give a user permissions for groups they aren't actually in, based on context.
|
||||||
|
* It will not change the group badges displayed for the user.
|
||||||
|
*
|
||||||
|
* @param callable $callable
|
||||||
|
*
|
||||||
|
* The callable can be a closure or invokable class, and should accept:
|
||||||
|
* - \Flarum\User\User $user: the user in question.
|
||||||
|
* - array $groupIds: an array of ids for the groups the user belongs to.
|
||||||
|
*
|
||||||
|
* The callable should return:
|
||||||
|
* - array $groupIds: an array of ids for the groups the user belongs to.
|
||||||
|
*/
|
||||||
|
public function permissionGroups(callable $callable)
|
||||||
|
{
|
||||||
|
$this->groupProcessors[] = $callable;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function extend(Container $container, Extension $extension = null)
|
public function extend(Container $container, Extension $extension = null)
|
||||||
{
|
{
|
||||||
$container->extend('flarum.user.display_name.supported_drivers', function ($existingDrivers) {
|
$container->extend('flarum.user.display_name.supported_drivers', function ($existingDrivers) {
|
||||||
return array_merge($existingDrivers, $this->displayNameDrivers);
|
return array_merge($existingDrivers, $this->displayNameDrivers);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$container->extend('flarum.user.group_processors', function ($existingRelations) {
|
||||||
|
return array_merge($existingRelations, $this->groupProcessors);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -83,6 +83,12 @@ class User extends AbstractModel
|
|||||||
*/
|
*/
|
||||||
protected $session;
|
protected $session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of callables, through each of which the user's list of groups is passed
|
||||||
|
* before being returned.
|
||||||
|
*/
|
||||||
|
protected static $groupProcessors = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of registered user preferences. Each preference is defined with
|
* An array of registered user preferences. Each preference is defined with
|
||||||
* a key, and its value is an array containing the following keys:.
|
* a key, and its value is an array containing the following keys:.
|
||||||
@@ -660,8 +666,13 @@ class User extends AbstractModel
|
|||||||
$groupIds = array_merge($groupIds, [Group::MEMBER_ID], $this->groups->pluck('id')->all());
|
$groupIds = array_merge($groupIds, [Group::MEMBER_ID], $this->groups->pluck('id')->all());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated, remove in beta 14.
|
||||||
event(new PrepareUserGroups($this, $groupIds));
|
event(new PrepareUserGroups($this, $groupIds));
|
||||||
|
|
||||||
|
foreach (static::$groupProcessors as $processor) {
|
||||||
|
$groupIds = $processor($this, $groupIds);
|
||||||
|
}
|
||||||
|
|
||||||
return Permission::whereIn('group_id', $groupIds);
|
return Permission::whereIn('group_id', $groupIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,6 +762,17 @@ class User extends AbstractModel
|
|||||||
static::$preferences[$key] = compact('transformer', 'default');
|
static::$preferences[$key] = compact('transformer', 'default');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a callback that processes a user's list of groups.
|
||||||
|
*
|
||||||
|
* @param callable $callback
|
||||||
|
* @return array $groupIds
|
||||||
|
*/
|
||||||
|
public static function addGroupProcessor($callback)
|
||||||
|
{
|
||||||
|
static::$groupProcessors[] = $callback;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the key for a preference which flags whether or not the user will
|
* Get the key for a preference which flags whether or not the user will
|
||||||
* receive a notification for $type via $method.
|
* receive a notification for $type via $method.
|
||||||
|
@@ -31,6 +31,10 @@ class UserServiceProvider extends AbstractServiceProvider
|
|||||||
{
|
{
|
||||||
$this->registerAvatarsFilesystem();
|
$this->registerAvatarsFilesystem();
|
||||||
$this->registerDisplayNameDrivers();
|
$this->registerDisplayNameDrivers();
|
||||||
|
|
||||||
|
$this->app->singleton('flarum.user.group_processors', function () {
|
||||||
|
return [];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function registerDisplayNameDrivers()
|
protected function registerDisplayNameDrivers()
|
||||||
@@ -72,6 +76,14 @@ class UserServiceProvider extends AbstractServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
|
foreach ($this->app->make('flarum.user.group_processors') as $callback) {
|
||||||
|
if (is_string($callback)) {
|
||||||
|
$callback = $this->app->make($callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
User::addGroupProcessor($callback);
|
||||||
|
}
|
||||||
|
|
||||||
User::setHasher($this->app->make('hash'));
|
User::setHasher($this->app->make('hash'));
|
||||||
User::setGate($this->app->make(Gate::class));
|
User::setGate($this->app->make(Gate::class));
|
||||||
User::setDisplayNameDriver($this->app->make('flarum.user.display_name.driver'));
|
User::setDisplayNameDriver($this->app->make('flarum.user.display_name.driver'));
|
||||||
|
@@ -24,7 +24,9 @@ class UserTest extends TestCase
|
|||||||
$this->prepareDatabase([
|
$this->prepareDatabase([
|
||||||
'users' => [
|
'users' => [
|
||||||
$this->adminUser(),
|
$this->adminUser(),
|
||||||
], 'settings' => [
|
$this->normalUser(),
|
||||||
|
],
|
||||||
|
'settings' => [
|
||||||
['key' => 'display_name_driver', 'value' => 'custom'],
|
['key' => 'display_name_driver', 'value' => 'custom'],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
@@ -58,6 +60,34 @@ class UserTest extends TestCase
|
|||||||
|
|
||||||
$this->assertEquals('admin@machine.local$$$suffix', $user->displayName);
|
$this->assertEquals('admin@machine.local$$$suffix', $user->displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function user_has_permissions_for_expected_groups_if_no_processors_added()
|
||||||
|
{
|
||||||
|
$this->prepDb();
|
||||||
|
$user = User::find(2);
|
||||||
|
|
||||||
|
$this->assertContains('viewUserList', $user->getPermissions());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function processor_can_restrict_user_groups()
|
||||||
|
{
|
||||||
|
$this->extend((new Extend\User)->permissionGroups(function (User $user, array $groupIds) {
|
||||||
|
return array_filter($groupIds, function ($id) {
|
||||||
|
return $id != 3;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
$this->prepDb();
|
||||||
|
$user = User::find(2);
|
||||||
|
|
||||||
|
$this->assertNotContains('viewUserList', $user->getPermissions());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomDisplayNameDriver implements DriverInterface
|
class CustomDisplayNameDriver implements DriverInterface
|
||||||
|
Reference in New Issue
Block a user