Commit 3e70e3f9 authored by Jacob Priddy's avatar Jacob Priddy 👌

refactor door group adding and removing to be better

parent 415d79a5
......@@ -244,10 +244,10 @@ class DoorsController extends ApiController
* This endpoint attaches a list of doors to a list of groups by ids.
*
* @authenticated
* @bodyParam doorIds[0] string[] required The list of door Ids to attach to. Example: 2
* @bodyParam doorIds[1] string[] required The list of door Ids to attach to. Example: 1
* @bodyParam groupIds[0] string[] required The list of group Ids to attach to. Example: 8
* @bodyParam groupIds[1] string[] required The list of group Ids to attach to. Example: 7
* @bodyParam door_ids[0] string[] required The list of door Ids to attach to. Example: 2
* @bodyParam door_ids[1] string[] required The list of door Ids to attach to. Example: 1
* @bodyParam group_ids[0] string[] required The list of group Ids to attach to. Example: 8
* @bodyParam group_ids[1] string[] required The list of group Ids to attach to. Example: 7
*
* @param \Source\UseCases\DoorGroup\AddDoorToGroup\AddDoorToGroupUseCase $addDoorToGroup
* @return \Illuminate\Http\JsonResponse
......@@ -260,15 +260,15 @@ class DoorsController extends ApiController
$this->authorizer->protectOne([Permissions::MANAGE_DOORS, Permissions::MANAGE_GROUPS]);
$this->validate($this->request, [
'groupIds' => 'array|required',
'doorIds' => 'array|required',
'group_ids' => 'array|required',
'door_ids' => 'array|required',
]);
$presenter = new AddDoorToGroupAPIPresenter();
$addDoorToGroup->addDoorToGroup(
$this->request->input('doorIds'),
$this->request->input('groupIds'),
$this->request->input('door_ids'),
$this->request->input('group_ids'),
$presenter
);
......@@ -281,10 +281,10 @@ class DoorsController extends ApiController
* This endpoint removes a list of doors from a list of groups by ids.
*
* @authenticated
* @bodyParam doorIds[0] string[] required The list of door Ids to attach to. Example: 2
* @bodyParam doorIds[1] string[] required The list of door Ids to attach to. Example: 1
* @bodyParam groupIds[0] string[] required The list of group Ids to attach to. Example: 8
* @bodyParam groupIds[1] string[] required The list of group Ids to attach to. Example: 7
* @bodyParam door_ids[0] string[] required The list of door Ids to attach to. Example: 2
* @bodyParam door_ids[1] string[] required The list of door Ids to attach to. Example: 1
* @bodyParam group_ids[0] string[] required The list of group Ids to attach to. Example: 8
* @bodyParam group_ids[1] string[] required The list of group Ids to attach to. Example: 7
*
* @param \Source\UseCases\DoorGroup\RemoveDoorFromGroup\RemoveDoorFromGroupUseCase $removeDoorFromGroup
* @return \Illuminate\Http\JsonResponse
......@@ -297,15 +297,15 @@ class DoorsController extends ApiController
$this->authorizer->protectOne([Permissions::MANAGE_DOORS, Permissions::MANAGE_GROUPS]);
$this->validate($this->request, [
'groupIds' => 'array|required',
'doorIds' => 'array|required',
'group_ids' => 'array|required',
'door_ids' => 'array|required',
]);
$presenter = new RemoveDoorFromGroupAPIPresenter();
$removeDoorFromGroup->removeDoorFromGroup(
$this->request->input('doorIds'),
$this->request->input('groupIds'),
$this->request->input('door_ids'),
$this->request->input('group_ids'),
$presenter
);
......
......@@ -235,26 +235,35 @@ class UsersController extends ApiController
* This route adds a user to a group
*
* @authenticated
* @urlParam userId required The user to add the group to. Example: 69
* @urlParam groupId required The group to add to the user. Example: 5
* @response 403 {"message":"You cannot modify your own admin privileges"}
* @bodyParam user_ids[0] string[] required The list of user ids to attach. Example: 69
* @bodyParam user_ids[1] string[] required The list of user ids to attach. Example: 420
* @bodyParam group_ids[0] string[] required The list of group Ids to attach to. Example: 4
* @bodyParam group_ids[1] string[] required The list of group Ids to attach to. Example: 5
*
* @param \Source\UseCases\GroupUser\AddUserToGroup\AddUserToGroupUseCase $useCase
* @param string $userId
* @param string $groupId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function addUserToGroup(AddUserToGroupUseCase $useCase, string $userId, string $groupId): JsonResponse
public function addUserToGroup(AddUserToGroupUseCase $useCase): JsonResponse
{
$this->authorizer->protect(Permissions::MANAGE_USERS);
$this->authorizer->protectOne([Permissions::MANAGE_USERS, Permissions::MANAGE_GROUPS]);
$this->validate($this->request, [
'group_ids' => 'array|required',
'user_ids' => 'array|required',
]);
$presenter = new AddUserToGroupAPIPresenter();
$useCase->addUserToGroup($userId, $groupId, $presenter);
$useCase->addUserToGroup(
$this->request->input('user_ids'),
$this->request->input('group_ids'),
$presenter
);
return $this->respondWithMessage($presenter->getViewModel()['message']);
return $this->respondWithData($presenter->getViewModel());
}
/**
......@@ -263,26 +272,35 @@ class UsersController extends ApiController
* This route removes a user from a group.
*
* @authenticated
* @urlParam userId required The user to remove the group from. Example: 69
* @urlParam groupId required The group to from from the user. Example: 5
* @response 403 {"message":"You cannot modify your own admin privileges"}
* @bodyParam user_ids[0] string[] required The list of user ids to attach. Example: 69
* @bodyParam user_ids[1] string[] required The list of user ids to attach. Example: 420
* @bodyParam group_ids[0] string[] required The list of group Ids to attach to. Example: 4
* @bodyParam group_ids[1] string[] required The list of group Ids to attach to. Example: 5
*
* @param \Source\UseCases\GroupUser\RemoveUserFromGroup\RemoveUserFromGroupUseCase $useCase
* @param string $userId
* @param string $groupId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function removeUserFromGroup(RemoveUserFromGroupUseCase $useCase, string $userId, string $groupId): JsonResponse
public function removeUserFromGroup(RemoveUserFromGroupUseCase $useCase): JsonResponse
{
$this->authorizer->protect(Permissions::MANAGE_USERS);
$this->authorizer->protectOne([Permissions::MANAGE_USERS, Permissions::MANAGE_GROUPS]);
$this->validate($this->request, [
'group_ids' => 'array|required',
'user_ids' => 'array|required',
]);
$presenter = new RemoveUserFromGroupAPIPresenter();
$useCase->removeUserFromGroup($userId, $groupId, $presenter);
$useCase->removeUserFromGroup(
$this->request->input('user_ids'),
$this->request->input('group_ids'),
$presenter
);
return $this->respondWithMessage($presenter->getViewModel()['message']);
return $this->respondWithData($presenter->getViewModel());
}
/**
......
......@@ -39,13 +39,16 @@ Route::group(['middleware' => 'auth:api'], static function () {
Route::delete('{userId}', [UsersController::class, 'delete'])->name('users.delete');
Route::get('{userId}/groups', [UsersController::class, 'getGroupsForUser']);
Route::post('{userId}/group/{groupId}', [UsersController::class, 'addUserToGroup'])
->name('users.group.add');
Route::delete('{userId}/group/{groupId}', [UsersController::class, 'removeUserFromGroup'])
->name('users.groups.delete');
Route::get('{userId}/doors', [UsersController::class, 'doors'])->name('users.doors');
});
Route::group([
'prefix' => 'group/user',
], static function () {
Route::post('/attach', [UsersController::class, 'addUserToGroup'])->name('group-user.attach');
Route::post('/detach', [UsersController::class, 'removeUserFromGroup'])->name('group-user.detach');
});
Route::group([
'prefix' => 'groups',
], static function () {
......
......@@ -31,7 +31,7 @@ class AddDoorToGroup implements AddDoorToGroupUseCase
$this->repository->addDoorToGroup($doorId, $groupId);
$response->addMessage("Attached door $doorId to group $groupId");
} catch (EntityNotFoundException $e) {
$response->addMessage("Failed to attach $doorId to $groupId. " . $e->getMessage());
$response->addMessage("Failed to attach door $doorId to group $groupId. " . $e->getMessage());
}
}
}
......
......@@ -2,26 +2,9 @@
namespace Source\UseCases\DoorGroup;
use Source\UseCases\HasMessages;
class ResponseModel
{
/**
* @var string[]
*/
protected array $messages = [];
/**
* @param string $message
*/
public function addMessage(string $message): void
{
$this->messages[] = $message;
}
/**
* @return string[]
*/
public function getMessages(): array
{
return $this->messages;
}
use HasMessages;
}
......@@ -11,7 +11,7 @@ class APIPresenter extends BasePresenter implements Presenter
/** @inheritDoc */
public function present(ResponseModel $responseModel): void
{
$this->viewModel['message'] = $responseModel->getMessage();
$this->viewModel['messages'] = $responseModel->getMessages();
}
/** @inheritDoc */
......
......@@ -3,6 +3,8 @@
namespace Source\UseCases\GroupUser\AddUserToGroup;
use Source\Authorization\Authorizer;
use Source\Exceptions\AuthorizationException;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\GroupUser\GroupUserRepository;
class AddUserToGroup implements AddUserToGroupUseCase
......@@ -30,14 +32,24 @@ class AddUserToGroup implements AddUserToGroupUseCase
/**
* @inheritDoc
*/
public function addUserToGroup(string $userId, string $groupId, Presenter $presenter): void
public function addUserToGroup(array $userIds, array $groupIds, Presenter $presenter): void
{
$this->authorizer->protectAdminRights($userId, $groupId);
$this->repository->addUserToGroup($userId, $groupId);
$responseModel = new ResponseModel('Success');
$presenter->present($responseModel);
$response = new ResponseModel();
foreach ($groupIds as $groupId) {
foreach ($userIds as $userId) {
try {
$this->authorizer->protectAdminRights($userId, $groupId);
$this->repository->addUserToGroup($userId, $groupId);
$response->addMessage("Attached user $userId to group $groupId");
} catch (EntityNotFoundException $e) {
$response->addMessage("Failed to attach user $userId to group $groupId. " . $e->getMessage());
} catch (AuthorizationException $e) {
$response->addMessage("Failed to attach user $userId to group $groupId. " . $e->getMessage());
}
}
}
$presenter->present($response);
}
}
......@@ -6,11 +6,9 @@ namespace Source\UseCases\GroupUser\AddUserToGroup;
interface AddUserToGroupUseCase
{
/**
* @param string $userId
* @param string $groupId
* @param string[] $userIds
* @param string[] $groupIds
* @param \Source\UseCases\GroupUser\AddUserToGroup\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\AuthorizationException
*/
public function addUserToGroup(string $userId, string $groupId, Presenter $presenter): void;
public function addUserToGroup(array $userIds, array $groupIds, Presenter $presenter): void;
}
......@@ -2,20 +2,9 @@
namespace Source\UseCases\GroupUser\AddUserToGroup;
use Source\UseCases\HasMessages;
class ResponseModel
{
/**
* @var string
*/
protected string $message;
public function __construct(string $message)
{
$this->message = $message;
}
public function getMessage(): string
{
return $this->message;
}
use HasMessages;
}
......@@ -11,7 +11,7 @@ class APIPresenter extends BasePresenter implements Presenter
/** @inheritDoc */
public function present(ResponseModel $responseModel): void
{
$this->viewModel['message'] = $responseModel->getMessage();
$this->viewModel['messages'] = $responseModel->getMessages();
}
/** @inheritDoc */
......
......@@ -3,6 +3,8 @@
namespace Source\UseCases\GroupUser\RemoveUserFromGroup;
use Source\Authorization\Authorizer;
use Source\Exceptions\AuthorizationException;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\GroupUser\GroupUserRepository;
class RemoveUserFromGroup implements RemoveUserFromGroupUseCase
......@@ -26,14 +28,24 @@ class RemoveUserFromGroup implements RemoveUserFromGroupUseCase
/**
* @inheritDoc
*/
public function removeUserFromGroup(string $userId, string $groupId, Presenter $presenter): void
public function removeUserFromGroup(array $userIds, array $groupIds, Presenter $presenter): void
{
$this->authorizer->protectAdminRights($userId, $groupId);
$this->repository->removeUserFromGroup($userId, $groupId);
$responseModel = new ResponseModel('Success');
$presenter->present($responseModel);
$response = new ResponseModel();
foreach ($groupIds as $groupId) {
foreach ($userIds as $userId) {
try {
$this->authorizer->protectAdminRights($userId, $groupId);
$this->repository->removeUserFromGroup($userId, $groupId);
$response->addMessage("Removed user $userId from group $groupId");
} catch (EntityNotFoundException $e) {
$response->addMessage("Failed to remove user $userId from group $groupId. " . $e->getMessage());
} catch (AuthorizationException $e) {
$response->addMessage("Failed to remove user $userId from group $groupId. " . $e->getMessage());
}
}
}
$presenter->present($response);
}
}
......@@ -8,11 +8,9 @@ interface RemoveUserFromGroupUseCase
/**
* Only Admins can add or remove other admins, but the overall admin user's groups cannot be modified
*
* @param string $userId
* @param string $groupId
* @param array $userIds
* @param array $groupIds
* @param \Source\UseCases\GroupUser\RemoveUserFromGroup\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\AuthorizationException
*/
public function removeUserFromGroup(string $userId, string $groupId, Presenter $presenter): void;
public function removeUserFromGroup(array $userIds, array $groupIds, Presenter $presenter): void;
}
......@@ -2,20 +2,9 @@
namespace Source\UseCases\GroupUser\RemoveUserFromGroup;
use Source\UseCases\HasMessages;
class ResponseModel
{
/**
* @var string
*/
protected string $message;
public function __construct(string $message)
{
$this->message = $message;
}
public function getMessage(): string
{
return $this->message;
}
use HasMessages;
}
<?php
namespace Source\UseCases;
trait HasMessages
{
/**
* @var string[]
*/
protected array $messages = [];
/**
* @param string $message
*/
public function addMessage(string $message): void
{
$this->messages[] = $message;
}
/**
* @return string[]
*/
public function getMessages(): array
{
return $this->messages;
}
}
......@@ -51,8 +51,8 @@ class AddDoorToGroupApiTest extends AuthenticatesWithApplicationTestCase
protected function handleTest(string $doorId, string $groupId): void
{
$this->response = $this->postJson('api/group/door/attach', [
'doorIds' => [$doorId],
'groupIds' => [$groupId],
'door_ids' => [$doorId],
'group_ids' => [$groupId],
'api_token' => $this->authToken,
]);
}
......
......@@ -51,8 +51,8 @@ class RemoveDoorFromGroupApiTest extends AuthenticatesWithApplicationTestCase
protected function handleTest(string $doorId, string $groupId): void
{
$this->response = $this->postJson('api/group/door/detach', [
'groupIds' => [$groupId],
'doorIds' => [$doorId],
'group_ids' => [$groupId],
'door_ids' => [$doorId],
'api_token' => $this->authToken,
]);
}
......
......@@ -33,8 +33,12 @@ class AddUserToGroupApiTest extends AuthenticatesWithApplicationTestCase
public function handleTest(string $userId, string $groupId): void
{
$this->response = $this->postJson(
"api/users/$userId/group/$groupId",
['api_token' => $this->authToken]
route('group-user.attach'),
[
'user_ids' => [$userId],
'group_ids' => [$groupId],
'api_token' => $this->authToken,
],
);
}
......@@ -71,14 +75,14 @@ class AddUserToGroupApiTest extends AuthenticatesWithApplicationTestCase
{
$this->authenticate();
$user = $this->usersRepository->create(new User(0, '', '', '', '', ''));
$group = $this->groups->create(new Group(0, '', ''));
$user = $this->usersRepository->create(new User(1234, '', '', '', '', ''));
$group = $this->groups->create(new Group(1235, '', ''));
$this->handleTest($user->getId(), $group->getId());
$this->response->assertStatus(200);
$this->response->assertJson(['message' => 'Success']);
$this->response->assertJson(['messages' => ['Attached user 1234 to group 1235']]);
self::assertEquals($group->getId(), $this->repository->getGroupsForUser($user->getId())[0]->getId());
}
}
......@@ -32,9 +32,13 @@ class RemoveUserFromGroupApiTest extends AuthenticatesWithApplicationTestCase
public function handleTest(string $userId, string $groupId): void
{
$this->response = $this->deleteJson(
"api/users/$userId/group/$groupId",
['api_token' => $this->authToken]
$this->response = $this->postJson(
route('group-user.detach'),
[
'user_ids' => [$userId],
'group_ids' => [$groupId],
'api_token' => $this->authToken,
]
);
}
......@@ -71,8 +75,8 @@ class RemoveUserFromGroupApiTest extends AuthenticatesWithApplicationTestCase
{
$this->authenticate();
$user = $this->usersRepository->create(new User(0, '', '', '', ''));
$group = $this->groups->create(new Group(0, '', ''));
$user = $this->usersRepository->create(new User(142, '', '', '', ''));
$group = $this->groups->create(new Group(241, '', ''));
$this->repository->addUserToGroup($user->getId(), $group->getId());
......@@ -82,7 +86,7 @@ class RemoveUserFromGroupApiTest extends AuthenticatesWithApplicationTestCase
$this->response->assertStatus(200);
$this->response->assertJson(['message' => 'Success']);
$this->response->assertJson(['messages' => ['Removed user 142 from group 241']]);
self::assertCount(0, $this->repository->getGroupsForUser($user->getId()));
}
}
......@@ -24,7 +24,9 @@ class PresenterTest extends TestCase
public function handleTest(string $message): void
{
$this->model = new ResponseModel($message);
$this->model = new ResponseModel();
$this->model->addMessage($message);
$this->presenter->present($this->model);
......@@ -36,6 +38,6 @@ class PresenterTest extends TestCase
{
$this->handleTest('message');
self::assertEquals(['message' => 'message'], $this->response);
self::assertEquals(['messages' => ['message']], $this->response);
}
}
......@@ -65,12 +65,10 @@ class UseCaseTest extends TestCase
/**
* @param string $userId
* @param string $groupId
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\AuthorizationException
*/
protected function handleTest(string $userId, string $groupId): void
{
$this->useCase->addUserToGroup($userId, $groupId, $this->presenter);
$this->useCase->addUserToGroup([$userId], [$groupId], $this->presenter);
$this->response = $this->presenter->response;
}
......@@ -78,7 +76,7 @@ class UseCaseTest extends TestCase
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityExistsException
*/
public function it_adds_a_user_to_a_group(): void
{
......@@ -103,8 +101,7 @@ class UseCaseTest extends TestCase
/**
* @test
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\EntityExistsException
*/
public function it_protects_admin_rights(): void
{
......