From 1d5586165c17485a2c794d3cc182a91e1fc01522 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Fri, 31 Jul 2015 20:10:49 +0930 Subject: [PATCH] Add group management actions to API --- .../src/Api/Actions/Groups/CreateAction.php | 40 ++++++++++ .../src/Api/Actions/Groups/DeleteAction.php | 34 ++++++++ .../src/Api/Actions/Groups/IndexAction.php | 30 ------- .../src/Api/Actions/Groups/UpdateAction.php | 43 ++++++++++ framework/core/src/Api/ApiServiceProvider.php | 7 -- .../core/src/Core/CoreServiceProvider.php | 3 +- .../src/Core/Groups/Commands/CreateGroup.php | 30 +++++++ .../Groups/Commands/CreateGroupHandler.php | 50 ++++++++++++ .../src/Core/Groups/Commands/DeleteGroup.php | 42 ++++++++++ .../Groups/Commands/DeleteGroupHandler.php | 45 +++++++++++ .../src/Core/Groups/Commands/EditGroup.php | 40 ++++++++++ .../Core/Groups/Commands/EditGroupHandler.php | 60 ++++++++++++++ framework/core/src/Core/Groups/Group.php | 78 ++++++++++++++++++- .../core/src/Core/Groups/GroupRepository.php | 50 ++++++++++++ .../src/Core/Groups/GroupsServiceProvider.php | 28 +++++++ framework/core/src/Events/GroupWasCreated.php | 21 +++++ framework/core/src/Events/GroupWasDeleted.php | 21 +++++ framework/core/src/Events/GroupWasRenamed.php | 21 +++++ .../core/src/Events/GroupWillBeDeleted.php | 40 ++++++++++ .../core/src/Events/GroupWillBeSaved.php | 40 ++++++++++ .../core/src/Events/RegisterApiRoutes.php | 19 ----- 21 files changed, 684 insertions(+), 58 deletions(-) create mode 100644 framework/core/src/Api/Actions/Groups/CreateAction.php create mode 100644 framework/core/src/Api/Actions/Groups/DeleteAction.php create mode 100644 framework/core/src/Api/Actions/Groups/UpdateAction.php create mode 100644 framework/core/src/Core/Groups/Commands/CreateGroup.php create mode 100644 framework/core/src/Core/Groups/Commands/CreateGroupHandler.php create mode 100644 framework/core/src/Core/Groups/Commands/DeleteGroup.php create mode 100644 framework/core/src/Core/Groups/Commands/DeleteGroupHandler.php create mode 100644 framework/core/src/Core/Groups/Commands/EditGroup.php create mode 100644 framework/core/src/Core/Groups/Commands/EditGroupHandler.php create mode 100644 framework/core/src/Core/Groups/GroupRepository.php create mode 100644 framework/core/src/Core/Groups/GroupsServiceProvider.php create mode 100644 framework/core/src/Events/GroupWasCreated.php create mode 100644 framework/core/src/Events/GroupWasDeleted.php create mode 100644 framework/core/src/Events/GroupWasRenamed.php create mode 100644 framework/core/src/Events/GroupWillBeDeleted.php create mode 100644 framework/core/src/Events/GroupWillBeSaved.php delete mode 100644 framework/core/src/Events/RegisterApiRoutes.php diff --git a/framework/core/src/Api/Actions/Groups/CreateAction.php b/framework/core/src/Api/Actions/Groups/CreateAction.php new file mode 100644 index 000000000..9580d94aa --- /dev/null +++ b/framework/core/src/Api/Actions/Groups/CreateAction.php @@ -0,0 +1,40 @@ +bus = $bus; + } + + /** + * Create a group according to input from the API request. + * + * @param JsonApiRequest $request + * @return \Flarum\Core\Groups\Group + */ + protected function create(JsonApiRequest $request) + { + return $this->bus->dispatch( + new CreateGroup($request->actor, $request->get('data')) + ); + } +} diff --git a/framework/core/src/Api/Actions/Groups/DeleteAction.php b/framework/core/src/Api/Actions/Groups/DeleteAction.php new file mode 100644 index 000000000..65ce085fe --- /dev/null +++ b/framework/core/src/Api/Actions/Groups/DeleteAction.php @@ -0,0 +1,34 @@ +bus = $bus; + } + + /** + * Delete a group. + * + * @param Request $request + */ + protected function delete(Request $request) + { + $this->bus->dispatch( + new DeleteGroup($request->get('id'), $request->actor) + ); + } +} diff --git a/framework/core/src/Api/Actions/Groups/IndexAction.php b/framework/core/src/Api/Actions/Groups/IndexAction.php index 8b57c07cc..05850d057 100644 --- a/framework/core/src/Api/Actions/Groups/IndexAction.php +++ b/framework/core/src/Api/Actions/Groups/IndexAction.php @@ -12,36 +12,6 @@ class IndexAction extends SerializeCollectionAction */ public $serializer = 'Flarum\Api\Serializers\GroupSerializer'; - /** - * @inheritdoc - */ - public $include = []; - - /** - * @inheritdoc - */ - public $link = []; - - /** - * @inheritdoc - */ - public $limitMax = 50; - - /** - * @inheritdoc - */ - public $limit = 20; - - /** - * @inheritdoc - */ - public $sortFields = []; - - /** - * @inheritdoc - */ - public $sort; - /** * Get the groups, ready to be serialized and assigned to the document * response. diff --git a/framework/core/src/Api/Actions/Groups/UpdateAction.php b/framework/core/src/Api/Actions/Groups/UpdateAction.php new file mode 100644 index 000000000..ea56e7674 --- /dev/null +++ b/framework/core/src/Api/Actions/Groups/UpdateAction.php @@ -0,0 +1,43 @@ +bus = $bus; + } + + /** + * Update a group according to input from the API request, and return it + * ready to be serialized and assigned to the JsonApi response. + * + * @param JsonApiRequest $request + * @param Document $document + * @return \Flarum\Core\Groups\Group + */ + protected function data(JsonApiRequest $request, Document $document) + { + return $this->bus->dispatch( + new EditGroup($request->get('id'), $request->actor, $request->get('data')) + ); + } +} diff --git a/framework/core/src/Api/ApiServiceProvider.php b/framework/core/src/Api/ApiServiceProvider.php index e08b42b8d..749ca364f 100644 --- a/framework/core/src/Api/ApiServiceProvider.php +++ b/framework/core/src/Api/ApiServiceProvider.php @@ -299,13 +299,6 @@ class ApiServiceProvider extends ServiceProvider $this->action('Flarum\Api\Actions\Groups\CreateAction') ); - // Show a single group - $routes->get( - '/groups/{id}', - 'flarum.api.groups.show', - $this->action('Flarum\Api\Actions\Groups\ShowAction') - ); - // Edit a group $routes->patch( '/groups/{id}', diff --git a/framework/core/src/Core/CoreServiceProvider.php b/framework/core/src/Core/CoreServiceProvider.php index 063701907..c5763d2f6 100644 --- a/framework/core/src/Core/CoreServiceProvider.php +++ b/framework/core/src/Core/CoreServiceProvider.php @@ -39,11 +39,12 @@ class CoreServiceProvider extends ServiceProvider { $this->app->singleton('flarum.forum', 'Flarum\Core\Forum'); - // TODO: probably use Illuminate's AggregateServiceProvider + // FIXME: probably use Illuminate's AggregateServiceProvider // functionality, because it includes the 'provides' stuff. $this->app->register('Flarum\Core\Activity\ActivityServiceProvider'); $this->app->register('Flarum\Core\Discussions\DiscussionsServiceProvider'); $this->app->register('Flarum\Core\Formatter\FormatterServiceProvider'); + $this->app->register('Flarum\Core\Groups\GroupsServiceProvider'); $this->app->register('Flarum\Core\Notifications\NotificationsServiceProvider'); $this->app->register('Flarum\Core\Posts\PostsServiceProvider'); $this->app->register('Flarum\Core\Users\UsersServiceProvider'); diff --git a/framework/core/src/Core/Groups/Commands/CreateGroup.php b/framework/core/src/Core/Groups/Commands/CreateGroup.php new file mode 100644 index 000000000..100e1e1cb --- /dev/null +++ b/framework/core/src/Core/Groups/Commands/CreateGroup.php @@ -0,0 +1,30 @@ +actor = $actor; + $this->data = $data; + } +} diff --git a/framework/core/src/Core/Groups/Commands/CreateGroupHandler.php b/framework/core/src/Core/Groups/Commands/CreateGroupHandler.php new file mode 100644 index 000000000..8211d1041 --- /dev/null +++ b/framework/core/src/Core/Groups/Commands/CreateGroupHandler.php @@ -0,0 +1,50 @@ +forum = $forum; + } + + /** + * @param CreateGroup $command + * @return Group + */ + public function handle(CreateGroup $command) + { + $actor = $command->actor; + $data = $command->data; + + $this->forum->assertCan($actor, 'createGroup'); + + $group = Group::build( + array_get($data, 'attributes.nameSingular'), + array_get($data, 'attributes.namePlural'), + array_get($data, 'attributes.color'), + array_get($data, 'attributes.icon') + ); + + event(new GroupWillBeSaved($group, $actor, $data)); + + $group->save(); + $this->dispatchEventsFor($group); + + return $group; + } +} diff --git a/framework/core/src/Core/Groups/Commands/DeleteGroup.php b/framework/core/src/Core/Groups/Commands/DeleteGroup.php new file mode 100644 index 000000000..5cc357990 --- /dev/null +++ b/framework/core/src/Core/Groups/Commands/DeleteGroup.php @@ -0,0 +1,42 @@ +groupId = $groupId; + $this->actor = $actor; + $this->data = $data; + } +} diff --git a/framework/core/src/Core/Groups/Commands/DeleteGroupHandler.php b/framework/core/src/Core/Groups/Commands/DeleteGroupHandler.php new file mode 100644 index 000000000..180bdf4cb --- /dev/null +++ b/framework/core/src/Core/Groups/Commands/DeleteGroupHandler.php @@ -0,0 +1,45 @@ +groups = $groups; + } + + /** + * @param DeleteGroup $command + * @return Group + * @throws \Flarum\Core\Exceptions\PermissionDeniedException + */ + public function handle(DeleteGroup $command) + { + $actor = $command->actor; + + $group = $this->groups->findOrFail($command->groupId, $actor); + + $group->assertCan($actor, 'delete'); + + event(new GroupWillBeDeleted($group, $actor, $command->data)); + + $group->delete(); + $this->dispatchEventsFor($group); + + return $group; + } +} diff --git a/framework/core/src/Core/Groups/Commands/EditGroup.php b/framework/core/src/Core/Groups/Commands/EditGroup.php new file mode 100644 index 000000000..3ef09cbdc --- /dev/null +++ b/framework/core/src/Core/Groups/Commands/EditGroup.php @@ -0,0 +1,40 @@ +groupId = $groupId; + $this->actor = $actor; + $this->data = $data; + } +} diff --git a/framework/core/src/Core/Groups/Commands/EditGroupHandler.php b/framework/core/src/Core/Groups/Commands/EditGroupHandler.php new file mode 100644 index 000000000..d2b715f3a --- /dev/null +++ b/framework/core/src/Core/Groups/Commands/EditGroupHandler.php @@ -0,0 +1,60 @@ +groups = $groups; + } + + /** + * @param EditGroup $command + * @return Group + * @throws \Flarum\Core\Exceptions\PermissionDeniedException + */ + public function handle(EditGroup $command) + { + $actor = $command->actor; + $data = $command->data; + + $group = $this->groups->findOrFail($command->groupId, $actor); + + $group->assertCan($actor, 'edit'); + + $attributes = array_get($data, 'attributes', []); + + if (isset($attributes['nameSingular']) && isset($attributes['namePlural'])) { + $group->rename($attributes['nameSingular'], $attributes['namePlural']); + } + + if (isset($attributes['color'])) { + $group->color = $attributes['color']; + } + + if (isset($attributes['icon'])) { + $group->icon = $attributes['icon']; + } + + event(new GroupWillBeSaved($group, $actor, $data)); + + $group->save(); + $this->dispatchEventsFor($group); + + return $group; + } +} diff --git a/framework/core/src/Core/Groups/Group.php b/framework/core/src/Core/Groups/Group.php index 96c0f6dc8..f4e8e0036 100755 --- a/framework/core/src/Core/Groups/Group.php +++ b/framework/core/src/Core/Groups/Group.php @@ -1,17 +1,39 @@ 'required', + 'name_plural' => 'required' + ]; + /** * The ID of the administrator group. */ @@ -27,6 +49,60 @@ class Group extends Model */ const MEMBER_ID = 3; + /** + * Boot the model. + * + * @return void + */ + public static function boot() + { + parent::boot(); + + static::deleted(function ($group) { + $group->raise(new GroupWasDeleted($group)); + + $group->permissions()->delete(); + }); + } + + /** + * Create a new group. + * + * @param string $nameSingular + * @param string $namePlural + * @param string $color + * @param string $icon + * @return static + */ + public static function build($nameSingular, $namePlural, $color, $icon) + { + $group = new static; + + $group->name_singular = $nameSingular; + $group->name_plural = $namePlural; + $group->color = $color; + $group->icon = $icon; + + $group->raise(new GroupWasCreated($group)); + + return $group; + } + + /** + * Rename the group. + * + * @param string $nameSingular + * @param string $namePlural + * @return $this + */ + public function rename($nameSingular, $namePlural) + { + $this->name_singular = $nameSingular; + $this->name_plural = $namePlural; + + return $this; + } + /** * Define the relationship with the group's users. * @@ -40,7 +116,7 @@ class Group extends Model /** * Define the relationship with the group's permissions. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function permissions() { diff --git a/framework/core/src/Core/Groups/GroupRepository.php b/framework/core/src/Core/Groups/GroupRepository.php new file mode 100644 index 000000000..2a8451462 --- /dev/null +++ b/framework/core/src/Core/Groups/GroupRepository.php @@ -0,0 +1,50 @@ +scopeVisibleTo($query, $actor)->firstOrFail(); + } + + /** + * Scope a query to only include records that are visible to a user. + * + * @param Builder $query + * @param User $actor + * @return Builder + */ + protected function scopeVisibleTo(Builder $query, User $actor = null) + { + if ($actor !== null) { + $query->whereVisibleTo($actor); + } + + return $query; + } +} diff --git a/framework/core/src/Core/Groups/GroupsServiceProvider.php b/framework/core/src/Core/Groups/GroupsServiceProvider.php new file mode 100644 index 000000000..868590b5b --- /dev/null +++ b/framework/core/src/Core/Groups/GroupsServiceProvider.php @@ -0,0 +1,28 @@ +app->make('validator')); + + $events = $this->app->make('events'); + + $events->listen(ModelAllow::class, function (ModelAllow $event) { + if ($event->model instanceof Group) { + if ($event->actor->hasPermission('group.'.$event->action)) { + return true; + } + } + }); + } +} diff --git a/framework/core/src/Events/GroupWasCreated.php b/framework/core/src/Events/GroupWasCreated.php new file mode 100644 index 000000000..a14b6c2a3 --- /dev/null +++ b/framework/core/src/Events/GroupWasCreated.php @@ -0,0 +1,21 @@ +group = $group; + } +} diff --git a/framework/core/src/Events/GroupWasDeleted.php b/framework/core/src/Events/GroupWasDeleted.php new file mode 100644 index 000000000..87fa1b9ac --- /dev/null +++ b/framework/core/src/Events/GroupWasDeleted.php @@ -0,0 +1,21 @@ +group = $group; + } +} diff --git a/framework/core/src/Events/GroupWasRenamed.php b/framework/core/src/Events/GroupWasRenamed.php new file mode 100644 index 000000000..9d9999434 --- /dev/null +++ b/framework/core/src/Events/GroupWasRenamed.php @@ -0,0 +1,21 @@ +group = $group; + } +} diff --git a/framework/core/src/Events/GroupWillBeDeleted.php b/framework/core/src/Events/GroupWillBeDeleted.php new file mode 100644 index 000000000..0d83b3173 --- /dev/null +++ b/framework/core/src/Events/GroupWillBeDeleted.php @@ -0,0 +1,40 @@ +group = $group; + $this->actor = $actor; + $this->data = $data; + } +} diff --git a/framework/core/src/Events/GroupWillBeSaved.php b/framework/core/src/Events/GroupWillBeSaved.php new file mode 100644 index 000000000..c11f99660 --- /dev/null +++ b/framework/core/src/Events/GroupWillBeSaved.php @@ -0,0 +1,40 @@ +group = $group; + $this->actor = $actor; + $this->data = $data; + } +} diff --git a/framework/core/src/Events/RegisterApiRoutes.php b/framework/core/src/Events/RegisterApiRoutes.php deleted file mode 100644 index aca6a9846..000000000 --- a/framework/core/src/Events/RegisterApiRoutes.php +++ /dev/null @@ -1,19 +0,0 @@ -routes = $routes; - } -}