Commit 8eaaa638 authored by Jacob Priddy's avatar Jacob Priddy 👌
Browse files

Add conntrollers and routes for attempts and entries

parent d7db4aba
<?php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
use Source\Authorization\Permissions;
use Source\UseCases\Attempts\GetAttempts\GetAttemptsUseCase;
use Source\UseCases\Attempts\GetAttemptsForDoor\GetAttemptsForDoorUseCase;
use Source\UseCases\Attempts\GetAttempts\APIPresenter as GetAttemptsAPIPresenter;
use Source\UseCases\Attempts\GetAttemptCountForDoor\GetAttemptCountForDoorUseCase;
use Source\UseCases\Attempts\GetAttemptCountForDoor\APIPresenter as AttemptCountAPIPresenter;
use Source\UseCases\Attempts\GetAttemptsForDoor\APIPresenter as GetAttemptsForDoorAPIPresenter;
class AttemptsController extends ApiController
{
/**
* @param \Source\UseCases\Attempts\GetAttemptCountForDoor\GetAttemptCountForDoorUseCase $count
* @param string $doorId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function count(GetAttemptCountForDoorUseCase $count, string $doorId): JsonResponse
{
$this->authorizer->protect(Permissions::ADMIN);
$this->validate($this->request, [
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
]);
$presenter = new AttemptCountAPIPresenter();
$count->count($doorId, $this->request->input('start'), $this->request->input('end'), $presenter);
return $this->respondWithData($presenter->getViewModel());
}
/**
* @param \Source\UseCases\Attempts\GetAttempts\GetAttemptsUseCase $attempts
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function index(GetAttemptsUseCase $attempts): JsonResponse
{
$this->authorizer->protect(Permissions::ADMIN);
$this->validate($this->request, [
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
]);
$presenter = new GetAttemptsAPIPresenter();
$attempts->getBetweenDates($this->request->input('start'), $this->request->input('end'), $presenter);
return $this->respondWithData($presenter->getViewModel());
}
/**
* @param \Source\UseCases\Attempts\GetAttemptsForDoor\GetAttemptsForDoorUseCase $doorAttempts
* @param string $doorId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function doorAttempts(GetAttemptsForDoorUseCase $doorAttempts, string $doorId): JsonResponse
{
$this->authorizer->protect(Permissions::ADMIN);
$this->validate($this->request, [
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
]);
$presenter = new GetAttemptsForDoorAPIPresenter();
$doorAttempts->getAttemptsForDoorBetween(
$doorId,
$this->request->input('start'),
$this->request->input('end'),
$presenter
);
return $this->respondWithData($presenter->getViewModel());
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
use Source\Authorization\Permissions;
use Source\UseCases\Entries\APIPresenter;
use Source\UseCases\Entries\GetEntriesForDoor\GetEntriesForDoorUseCase;
use Source\UseCases\Entries\GetEntriesForUser\GetEntriesForUserUseCase;
use Source\UseCases\Entries\GetEntriesForDoorAndUser\GetEntriesForDoorAndUserUseCase;
class EntriesController extends ApiController
{
/**
* @param \Source\UseCases\Entries\GetEntriesForDoor\GetEntriesForDoorUseCase $doorEntries
* @param string $doorId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function doorEntries(GetEntriesForDoorUseCase $doorEntries, string $doorId): JsonResponse
{
$this->authorizer->protect(Permissions::ADMIN);
$this->validate($this->request, [
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
]);
$presenter = new APIPresenter();
$doorEntries->getEntriesForDoorBetween(
$doorId,
$this->request->input('start'),
$this->request->input('end'),
$presenter
);
return $this->respondWithData($presenter->getViewModel());
}
/**
* @param \Source\UseCases\Entries\GetEntriesForUser\GetEntriesForUserUseCase $userEntries
* @param string $userId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function userEntries(GetEntriesForUserUseCase $userEntries, string $userId): JsonResponse
{
$this->authorizer->protect(Permissions::ADMIN);
$this->validate($this->request, [
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
]);
$presenter = new APIPresenter();
$userEntries->getEntriesForUserBetween(
$userId,
$this->request->input('start'),
$this->request->input('end'),
$presenter
);
return $this->respondWithData($presenter->getViewModel());
}
/**
* @param \Source\UseCases\Entries\GetEntriesForDoorAndUser\GetEntriesForDoorAndUserUseCase $doorUserEntries
* @param string $doorId
* @param string $userId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function doorUserEntries(
GetEntriesForDoorAndUserUseCase $doorUserEntries,
string $doorId,
string $userId
): JsonResponse {
$this->authorizer->protect(Permissions::ADMIN);
$this->validate($this->request, [
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
]);
$presenter = new APIPresenter();
$doorUserEntries->getEntriesForDoorAndUserBetween(
$doorId,
$userId,
$this->request->input('start'),
$this->request->input('end'),
$presenter
);
return $this->respondWithData($presenter->getViewModel());
}
}
......@@ -7,6 +7,8 @@ use App\Http\Controllers\DoorsController;
use App\Http\Controllers\UsersController;
use App\Http\Controllers\GroupsController;
use App\Http\Controllers\TokensController;
use App\Http\Controllers\EntriesController;
use App\Http\Controllers\AttemptsController;
/*
|--------------------------------------------------------------------------
......@@ -32,6 +34,8 @@ Route::group(['middleware' => 'auth:api'], static function () {
Route::patch('{userId}', [UsersController::class, 'update']);
Route::delete('{userId}', [UsersController::class, 'delete']);
Route::get('{userId}/entries', [EntriesController::class, 'userEntries']);
Route::get('{userId}/groups', [UsersController::class, 'getGroupsForUser']);
Route::post('{userId}/group/{groupId}', [UsersController::class, 'addUserToGroup']);
Route::delete('{userId}/group/{groupId}', [UsersController::class, 'removeUserFromGroup']);
......@@ -61,6 +65,10 @@ Route::group(['middleware' => 'auth:api'], static function () {
Route::post('/{doorId}/regenerate-token', [DoorsController::class, 'regenerateToken']);
Route::delete('{doorId}', [DoorsController::class, 'delete']);
Route::get('{doorId}/entries', [EntriesController::class, 'doorEntries']);
Route::get('{doorId}/attempts', [AttemptsController::class, 'doorAttempts']);
Route::get('{doorId}/attempts/count', [AttemptsController::class, 'count']);
Route::get('{doorId}/groups', [DoorsController::class, 'getGroupsForDoor']);
Route::post('{doorId}/group/{groupId}', [DoorsController::class, 'addDoorToGroup']);
Route::delete('{doorId}/group/{groupId}', [DoorsController::class, 'removeDoorFromGroup']);
......@@ -76,6 +84,19 @@ Route::group(['middleware' => 'auth:api'], static function () {
Route::post('{tokenId}/expire', [TokensController::class, 'expire']);
});
Route::group([
'prefix' => 'entries',
], static function () {
Route::get('user/{userId}/door/{doorId}', [EntriesController::class, 'doorUserEntries']);
Route::get('door/{doorId}/user/{userId}', [EntriesController::class, 'doorUserEntries']);
});
Route::group([
'prefix' => 'attempts',
], static function () {
Route::get('/', [AttemptsController::class, 'index']);
});
Route::group([
'prefix' => 'me',
], static function () {
......
......@@ -3,6 +3,8 @@
namespace Source\UseCases\Attempts\GetAttemptCountForDoor;
use Carbon\Carbon;
use Source\Gateways\Doors\DoorsRepository;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\Attempts\AttemptsRepository;
class GetAttemptCountForDoor implements GetAttemptCountForDoorUseCase
......@@ -12,9 +14,15 @@ class GetAttemptCountForDoor implements GetAttemptCountForDoorUseCase
*/
protected AttemptsRepository $attempts;
public function __construct(AttemptsRepository $attempts)
/**
* @var \Source\Gateways\Doors\DoorsRepository
*/
protected DoorsRepository $doors;
public function __construct(AttemptsRepository $attempts, DoorsRepository $doors)
{
$this->attempts = $attempts;
$this->doors = $doors;
}
/**
......@@ -22,6 +30,10 @@ class GetAttemptCountForDoor implements GetAttemptCountForDoorUseCase
*/
public function count(string $doorId, string $begin, string $end, Presenter $presenter): void
{
if (!$this->doors->exists($doorId)) {
throw new EntityNotFoundException();
}
$count = $this->attempts->getCountForDoorBetween($doorId, new Carbon($begin), new Carbon($end));
$responseModel = new ResponseModel($count);
......
......@@ -12,6 +12,7 @@ interface GetAttemptCountForDoorUseCase
* @param string $begin
* @param string $end
* @param \Source\UseCases\Attempts\GetAttemptCountForDoor\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function count(string $doorId, string $begin, string $end, Presenter $presenter): void;
......
......@@ -4,6 +4,7 @@
namespace Source\UseCases\Attempts\GetAttemptCountForDoor;
use Illuminate\Support\ServiceProvider;
use Source\Gateways\Doors\DoorsRepository;
use Illuminate\Contracts\Foundation\Application;
use Source\Gateways\Attempts\AttemptsRepository;
use Illuminate\Contracts\Support\DeferrableProvider;
......@@ -21,7 +22,7 @@ class GetAttemptCountForDoorUseCaseServiceProvider extends ServiceProvider imple
public function register()
{
$this->app->bind(GetAttemptCountForDoorUseCase::class, static function (Application $app) {
return new GetAttemptCountForDoor($app->make(AttemptsRepository::class));
return new GetAttemptCountForDoor($app->make(AttemptsRepository::class), $app->make(DoorsRepository::class));
});
}
......
......@@ -3,6 +3,8 @@
namespace Source\UseCases\Attempts\GetAttemptsForDoor;
use Carbon\Carbon;
use Source\Gateways\Doors\DoorsRepository;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\Attempts\AttemptsRepository;
class GetAttemptsForDoor implements GetAttemptsForDoorUseCase
......@@ -12,9 +14,15 @@ class GetAttemptsForDoor implements GetAttemptsForDoorUseCase
*/
protected AttemptsRepository $attempts;
public function __construct(AttemptsRepository $attempts)
/**
* @var \Source\Gateways\Doors\DoorsRepository
*/
protected DoorsRepository $doors;
public function __construct(AttemptsRepository $attempts, DoorsRepository $doors)
{
$this->attempts = $attempts;
$this->doors = $doors;
}
/**
......@@ -22,6 +30,10 @@ class GetAttemptsForDoor implements GetAttemptsForDoorUseCase
*/
public function getAttemptsForDoorBetween(string $doorId, string $begin, string $end, Presenter $presenter): void
{
if (!$this->doors->exists($doorId)) {
throw new EntityNotFoundException();
}
$attempts = $this->attempts->getForDoorBetween($doorId, new Carbon($begin), new Carbon($end));
$response = new ResponseModel($attempts);
......
......@@ -12,6 +12,7 @@ interface GetAttemptsForDoorUseCase
* @param string $begin
* @param string $end
* @param \Source\UseCases\Attempts\GetAttemptsForDoor\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function getAttemptsForDoorBetween(string $doorId, string $begin, string $end, Presenter $presenter): void;
......
......@@ -4,6 +4,7 @@
namespace Source\UseCases\Attempts\GetAttemptsForDoor;
use Illuminate\Support\ServiceProvider;
use Source\Gateways\Doors\DoorsRepository;
use Illuminate\Contracts\Foundation\Application;
use Source\Gateways\Attempts\AttemptsRepository;
use Illuminate\Contracts\Support\DeferrableProvider;
......@@ -21,7 +22,7 @@ class GetAttemptsForDoorUseCaseServiceProvider extends ServiceProvider implement
public function register()
{
$this->app->bind(GetAttemptsForDoorUseCase::class, static function (Application $app) {
return new GetAttemptsForDoor($app->make(AttemptsRepository::class));
return new GetAttemptsForDoor($app->make(AttemptsRepository::class), $app->make(DoorsRepository::class));
});
}
......
......@@ -4,7 +4,9 @@ namespace Source\UseCases\Entries\GetEntriesForDoor;
use Carbon\Carbon;
use Source\UseCases\Entries\Presenter;
use Source\Gateways\Doors\DoorsRepository;
use Source\UseCases\Entries\ResponseModel;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\Entries\EntriesRepository;
class GetEntriesForDoor implements GetEntriesForDoorUseCase
......@@ -14,17 +16,27 @@ class GetEntriesForDoor implements GetEntriesForDoorUseCase
*/
protected EntriesRepository $entries;
public function __construct(EntriesRepository $entries)
/**
* @var \Source\Gateways\Doors\DoorsRepository
*/
protected DoorsRepository $doors;
public function __construct(EntriesRepository $entries, DoorsRepository $doors)
{
$this->entries = $entries;
$this->doors = $doors;
}
/**
* @inheritDoc
*/
public function getEntriesForDoorBetween(string $door, string $begin, string $end, Presenter $presenter): void
public function getEntriesForDoorBetween(string $doorId, string $begin, string $end, Presenter $presenter): void
{
$entries = $this->entries->getForDoorBetween($door, new Carbon($begin), new Carbon($end));
if (!$this->doors->exists($doorId)) {
throw new EntityNotFoundException();
}
$entries = $this->entries->getForDoorBetween($doorId, new Carbon($begin), new Carbon($end));
$response = new ResponseModel($entries);
......
......@@ -10,11 +10,12 @@ interface GetEntriesForDoorUseCase
/**
* Begin and end must be parsable by datetime
*
* @param string $door
* @param string $doorId
* @param string $begin
* @param string $end
* @param \Source\UseCases\Entries\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function getEntriesForDoorBetween(string $door, string $begin, string $end, Presenter $presenter): void;
public function getEntriesForDoorBetween(string $doorId, string $begin, string $end, Presenter $presenter): void;
}
......@@ -4,6 +4,7 @@
namespace Source\UseCases\Entries\GetEntriesForDoor;
use Illuminate\Support\ServiceProvider;
use Source\Gateways\Doors\DoorsRepository;
use Source\Gateways\Entries\EntriesRepository;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Support\DeferrableProvider;
......@@ -21,7 +22,7 @@ class GetEntriesForDoorUseCaseServiceProvider extends ServiceProvider implements
public function register()
{
$this->app->bind(GetEntriesForDoorUseCase::class, static function (Application $app) {
return new GetEntriesForDoor($app->make(EntriesRepository::class));
return new GetEntriesForDoor($app->make(EntriesRepository::class), $app->make(DoorsRepository::class));
});
}
......
......@@ -4,7 +4,10 @@ namespace Source\UseCases\Entries\GetEntriesForDoorAndUser;
use Carbon\Carbon;
use Source\UseCases\Entries\Presenter;
use Source\Gateways\Doors\DoorsRepository;
use Source\Gateways\Users\UsersRepository;
use Source\UseCases\Entries\ResponseModel;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\Entries\EntriesRepository;
class GetEntriesForDoorAndUser implements GetEntriesForDoorAndUserUseCase
......@@ -14,9 +17,21 @@ class GetEntriesForDoorAndUser implements GetEntriesForDoorAndUserUseCase
*/
protected EntriesRepository $entries;
public function __construct(EntriesRepository $entries)
/**
* @var \Source\Gateways\Doors\DoorsRepository
*/
protected DoorsRepository $doors;
/**
* @var \Source\Gateways\Users\UsersRepository
*/
protected UsersRepository $users;
public function __construct(EntriesRepository $entries, DoorsRepository $doors, UsersRepository $users)
{
$this->entries = $entries;
$this->doors = $doors;
$this->users = $users;
}
/**
......@@ -29,6 +44,10 @@ class GetEntriesForDoorAndUser implements GetEntriesForDoorAndUserUseCase
string $end,
Presenter $presenter
): void {
if (!$this->doors->exists($doorId) || !$this->users->exists($userId)) {
throw new EntityNotFoundException();
}
$entries = $this->entries->getForUserAndDoorBetween(
$userId,
$doorId,
......
......@@ -15,6 +15,7 @@ interface GetEntriesForDoorAndUserUseCase
* @param string $begin
* @param string $end
* @param \Source\UseCases\Entries\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function getEntriesForDoorAndUserBetween(
......
......@@ -4,6 +4,8 @@
namespace Source\UseCases\Entries\GetEntriesForDoorAndUser;
use Illuminate\Support\ServiceProvider;
use Source\Gateways\Doors\DoorsRepository;
use Source\Gateways\Users\UsersRepository;
use Source\Gateways\Entries\EntriesRepository;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Support\DeferrableProvider;
......@@ -21,7 +23,11 @@ class GetEntriesForDoorAndUserUseCaseServiceProvider extends ServiceProvider imp
public function register()
{
$this->app->bind(GetEntriesForDoorAndUserUseCase::class, static function (Application $app) {
return new GetEntriesForDoorAndUser($app->make(EntriesRepository::class));
return new GetEntriesForDoorAndUser(
$app->make(EntriesRepository::class),
$app->make(DoorsRepository::class),
$app->make(UsersRepository::class)
);
});
}
......
......@@ -4,7 +4,9 @@ namespace Source\UseCases\Entries\GetEntriesForUser;
use Carbon\Carbon;
use Source\UseCases\Entries\Presenter;
use Source\Gateways\Users\UsersRepository;
use Source\UseCases\Entries\ResponseModel;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\Entries\EntriesRepository;
class GetEntriesForUser implements GetEntriesForUserUseCase
......@@ -14,9 +16,15 @@ class GetEntriesForUser implements GetEntriesForUserUseCase
*/
protected EntriesRepository $entries;
public function __construct(EntriesRepository $entries)
/**
* @var \Source\Gateways\Users\UsersRepository
*/
protected UsersRepository $users;
public function __construct(EntriesRepository $entries, UsersRepository $users)
{
$this->entries = $entries;
$this->users = $users;
}
/**
......@@ -24,6 +32,10 @@ class GetEntriesForUser implements GetEntriesForUserUseCase
*/
public function getEntriesForUserBetween(string $userId, string $begin, string $end, Presenter $presenter): void
{
if (!$this->users->exists($userId)) {
throw new EntityNotFoundException();
}
$entries = $this->entries->getForUserBetween($userId, new Carbon($begin), new Carbon($end));
$response = new ResponseModel($entries);
......
......@@ -14,6 +14,7 @@ interface GetEntriesForUserUseCase
* @param string $begin
* @param string $end
* @param \Source\UseCases\Entries\Presenter $presenter
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Exception
*/
public function getEntriesForUserBetween(string $userId, string $begin, string $end, Presenter $presenter): void;
......
......@@ -4,6 +4,7 @@
namespace Source\UseCases\Entries\GetEntriesForUser;
use Illuminate\Support\ServiceProvider;
use Source\Gateways\Users\UsersRepository;
use Source\Gateways\Entries\EntriesRepository;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Support\DeferrableProvider;
......@@ -21,7 +22,7 @@ class GetEntriesForUserUseCaseServiceProvider extends ServiceProvider implements