Commit d9721022 authored by Jacob Priddy's avatar Jacob Priddy 👌

Do users on admin panel

parent 1637e940
......@@ -53,7 +53,7 @@ class UsersController extends ApiController
$this->authorizer->protect(Permissions::MANAGE_USERS);
$this->validate($this->request, [
'query' => 'string',
'query' => 'nullable|string',
]);
$presenter = new AllUsersAPIPresenter();
......
......@@ -6,7 +6,6 @@ namespace App\Http\Controllers\Web\Admin;
use Illuminate\View\View;
use App\Http\Controllers\Controller;
use Source\Authorization\Permissions;
use Illuminate\Http\RedirectResponse;
use Source\UseCases\Doors\CreateDoor\CreateDoorUseCase;
use Source\UseCases\Doors\GetDoor\APIPresenter as GetDoorPresenter;
......@@ -27,13 +26,9 @@ class DoorsController extends Controller
* @param \Source\UseCases\Doors\GetDoors\GetDoorsUseCase $doors
* @return \Illuminate\View\View
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function index(GetDoorsUseCase $doors): View
{
$this->authorizer->protect(Permissions::MANAGE_DOORS);
$this->validate($this->request, [
'query' => 'nullable|string',
'awol_seconds' => 'nullable|int',
......@@ -50,13 +45,10 @@ class DoorsController extends Controller
* @param string $doorId
* @param \Source\UseCases\Doors\GetDoor\GetDoorUseCase $getDoor
* @return \Illuminate\View\View
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function edit(string $doorId, GetDoorUseCase $getDoor): View
{
$this->authorizer->protect(Permissions::MANAGE_DOORS);
$presenter = new GetDoorPresenter();
$getDoor->get($doorId, $presenter);
......@@ -76,14 +68,11 @@ class DoorsController extends Controller
* @param \Source\UseCases\Doors\UpdateDoor\UpdateDoorUseCase $updateDoor
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\EntityExistsException
*/
public function update(string $doorId, UpdateDoorUseCase $updateDoor): RedirectResponse
{
$this->authorizer->protect(Permissions::MANAGE_DOORS);
$this->validate($this->request, [
'location' => 'required|string|max:255',
'name' => 'required|string|max:255',
......@@ -99,14 +88,10 @@ class DoorsController extends Controller
* @param \Source\UseCases\Doors\CreateDoor\CreateDoorUseCase $createDoor
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\AuthorizationException
* @throws \Source\Exceptions\EntityExistsException
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function create(CreateDoorUseCase $createDoor): RedirectResponse
{
$this->authorizer->protect(Permissions::MANAGE_DOORS);
$this->validate($this->request, [
'location' => 'required|string|max:255',
'name' => 'required|string|max:255',
......@@ -124,12 +109,9 @@ class DoorsController extends Controller
* @param \Source\UseCases\Doors\DeleteDoor\DeleteDoorUseCase $deleteDoor
* @return \Illuminate\Http\RedirectResponse
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\AuthorizationException
*/
public function delete(string $doorId, DeleteDoorUseCase $deleteDoor): RedirectResponse
{
$this->authorizer->protect(Permissions::MANAGE_DOORS);
$presenter = new DeleteDoorPresenter();
$deleteDoor->delete($doorId, $presenter);
......@@ -143,12 +125,9 @@ class DoorsController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @throws \Source\Exceptions\EntityExistsException
* @throws \Source\Exceptions\EntityNotFoundException
* @throws \Source\Exceptions\AuthorizationException
*/
public function regenerateToken(string $doorId, GenerateDoorTokenUseCase $tokenGenerator): RedirectResponse
{
$this->authorizer->protect(Permissions::MANAGE_DOORS);
$presenter = new WebTokenGeneratePresenter();
$tokenGenerator->generate($doorId, $presenter);
......
<?php
namespace App\Http\Controllers\Web\Admin;
use Illuminate\View\View;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Source\Exceptions\DeleteFailedException;
use Source\Exceptions\AuthorizationException;
use Source\UseCases\Users\UpdateUser\UpdateUserUseCase;
use Source\UseCases\Users\CreateUser\CreateUserUseCase;
use Source\UseCases\Users\GetUser\WebPresenter as GetUserPresenter;
use Source\UseCases\Users\GetUsers\WebPresenter as GetUsersPresenter;
use Source\UseCases\Users\GetUser\GetUserUseCase;
use Source\UseCases\Users\DeleteUser\APIPresenter as DeleteUserPresenter;
use Source\UseCases\Users\GetUsers\GetUsersUseCase;
use Source\UseCases\Users\DeleteUser\DeleteUserUseCase;
use Source\UseCases\Users\UpdateUser\WebPresenter as UpdateUserPresenter;
use Source\UseCases\Users\CreateUser\WebPresenter as CreateUserPresenter;
class UsersController extends Controller
{
/**
* @param \Source\UseCases\Users\GetUsers\GetUsersUseCase $users
* @return \Illuminate\View\View
* @throws \Illuminate\Validation\ValidationException
*/
public function index(GetUsersUseCase $users): View
{
$this->validate($this->request, [
'query' => 'nullable|string',
]);
$presenter = new GetUsersPresenter();
$users->search($this->request->input('query'), $presenter);
return view('admin.users', $presenter->getViewModel($this->request->all()));
}
/**
* @param \Source\UseCases\Users\CreateUser\CreateUserUseCase $createUser
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\EntityExistsException
*/
public function create(CreateUserUseCase $createUser): RedirectResponse
{
$this->validate($this->request, [
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'display_name' => 'required|string|max:255',
'email' => 'required|email|max:255',
'emplid' => 'nullable|string|max:8|min:5',
'password' => 'nullable|string|min:15|max:255',
'doorcode' => 'nullable|string|numeric|digits_between:4,255',
'expires_at' => 'nullable|string|date|max:255',
]);
$presenter = new CreateUserPresenter();
$createUser->create($this->request->all(), $presenter);
return redirect(route('web.admin.users.index'))->with($presenter->getViewModel());
}
/**
* @param string $userId
* @param \Source\UseCases\Users\GetUser\GetUserUseCase $user
* @return \Illuminate\View\View
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function edit(string $userId, GetUserUseCase $user): View
{
$presenter = new GetUserPresenter();
$user->get($userId, $presenter);
$u = $presenter->getViewModel()['user'];
$this->request->session()->flashInput([
'first_name' => $u['first_name'],
'last_name' => $u['last_name'],
'display_name' => $u['display_name'],
'emplid' => $u['emplid'] ?? '',
'email' => $u['email'],
'expires_at' => $u['expires_at'],
]);
return view('admin.entities.user', ['id' => $u['id']]);
}
/**
* @param string $userId
* @param \Source\UseCases\Users\UpdateUser\UpdateUserUseCase $updateUser
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException
* @throws \Source\Exceptions\EntityExistsException
*/
public function update(string $userId, UpdateUserUseCase $updateUser): RedirectResponse
{
$this->validate($this->request, [
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'display_name' => 'required|string|max:255',
'email' => 'required|email|max:255',
'emplid' => 'nullable|string|max:8|min:5',
'password' => 'nullable|string|max:255',
'doorcode' => 'nullable|string|numeric|digits_between:4,255',
'expires_at' => 'nullable|string|date|max:255',
]);
$presenter = new UpdateUserPresenter();
try {
$updateUser->update($userId, $this->request->all(), $presenter);
} catch (AuthorizationException $e) {
return redirect()->back()->with(['error' => $e->getMessage()]);
}
return redirect(route('web.admin.users.index'))->with($presenter->getViewModel());
}
/**
* @param string $userId
* @param \Source\UseCases\Users\DeleteUser\DeleteUserUseCase $deleteUser
* @return \Illuminate\Http\RedirectResponse
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function delete(string $userId, DeleteUserUseCase $deleteUser): RedirectResponse
{
$presenter = new DeleteUserPresenter();
$message = null;
try {
$deleteUser->delete($userId, $presenter);
} catch (DeleteFailedException $e) {
$message = ['message' => $e->getMessage()];
} catch (AuthorizationException $e) {
$message = ['message' => $e->getMessage()];
}
return redirect()->back()->with($message ?? $presenter->getViewModel());
}
}
......@@ -30,9 +30,9 @@
placeholder="CSP316">
</div>
@if(request()->route()->named('*.build'))
<button type="submit" class="btn btn-success">Create Door</button>
<button type="submit" class="btn btn-primary">Create Door</button>
@else
<button type="submit" class="btn btn-success">Update Door</button>
<button type="submit" class="btn btn-primary">Update Door</button>
@endif
</form>
</div>
......
@extends('layouts.admin')
@section('title', 'Build User')
@section('main-content')
<div class="row">
<div class="col-8 offset-2">
@include('partials.message')
@include('partials.form-errors')
@if(request()->route()->named('*.build'))
<form method="POST" action="{{ route('web.admin.users.create') }}">
@else
<form method="POST" action="{{ route('web.admin.users.update', ['userId' => $id]) }}">
@method('PUT')
@endif
@csrf
<div class="form-group">
<label for="first_name">
First Name
</label>
<span class="text-muted float-right">required</span>
<input type="text" name="first_name" class="form-control" id="first_name"
value="{{ old('first_name') }}"
placeholder="Jacob">
</div>
<div class="form-group">
<label for="last_name">
Last Name
</label>
<span class="text-muted float-right">required</span>
<input type="text" name="last_name" class="form-control" id="last_name"
value="{{ old('last_name') }}"
placeholder="Priddy">
</div>
<div class="form-group">
<label for="display_name">
Display Name
</label>
<span class="text-muted float-right">required</span>
<input type="text" name="display_name" class="form-control" id="display_name"
value="{{ old('display_name') }}"
placeholder="Jacob Priddy">
</div>
<div class="form-group">
<label for="email">
E-Mail
</label>
<span class="text-muted float-right">required</span>
<input type="email" name="email" class="form-control" id="email"
value="{{ old('email') }}"
placeholder="jacob.priddy@wallawalla.edu">
</div>
<div class="form-group">
<label for="emplid">
Employee ID
</label>
<input type="text" name="emplid" class="form-control" id="emplid"
value="{{ old('emplid') }}"
placeholder="250442">
</div>
<div class="form-group">
<label for="password">
Password (Used when bypassing ADFS)
</label>
<input type="password" name="password" class="form-control" id="password">
</div>
<div class="form-group">
<label for="doorcode">
Door code (Student ID is NOT automatically prepended when submitted. What you put in here is absolute.)
</label>
<input type="password" name="doorcode" class="form-control" id="doorcode">
</div>
<div class="form-group">
<label for="expires_at">
Expires Date
</label>
<input type="date" name="expires_at" class="form-control" id="expires_at"
value="{{ old('expires_at') }}">
</div>
@if(request()->route()->named('*.build'))
<button type="submit" class="btn btn-primary">Create User</button>
@else
<button type="submit" class="btn btn-primary">Update User</button>
@endif
</form>
</div>
</div>
@endsection
@extends('layouts.admin')
@section('title', 'View Users')
@section('main-content')
@include('partials.message')
@include('partials.form-errors')
<div class="card shadow mb-4">
<div class="card-header py-3">
<div class="row">
<div class="col-6">
<h4 class="m-0 font-weight-bold text-primary float-left">Users</h4>
</div>
<div class="col-6">
<a class="float-right btn btn-primary" href="{{ route('web.admin.users.build') }}">
New User
</a>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive overflow-hidden">
{{-- Search/filter options--}}
<form action="{{ route('web.admin.users.index') }}" method="GET">
<div class="form-row">
<div class="form-inline col-sm-12 col-md-6">
@include('partials.perPage')
</div>
<div class="form-inline col-sm-12 col-md-6">
<label class="sr-only" for="query">
Search
</label>
<input id="query" type="text" name="query" placeholder="Search"
value="{{ request('query') }}">
<div class="input-group-append">
<button class="btn btn-primary" type="submit">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</div>
</form>
<hr>
@include('partials.table', ['headers' => $headers, 'paginatedData' => $users, 'controls' => 'user'])
</div>
</div>
</div>
@endsection
......@@ -70,7 +70,7 @@
@can(\Source\Authorization\Permissions::MANAGE_USERS)
<li class="nav-item {{ Nav::hasSegment('users', 2) }}">
<a class="nav-link" href="{{ route('web.admin.profile') }}">
<a class="nav-link" href="{{ route('web.admin.users.index') }}">
<i class="fas fa-fw fa-user"></i>
<span>Users</span>
</a>
......
<div class="d-flex flex-row">
{{-- <a class="btn btn-dark" href="{{ route('web.admin.doors.schedule', ['doorId' => $id]) }}" data-toggle="tooltip" title="View Open Mode Schedule">--}}
{{-- <i class="fas fa-calendar-alt"></i>--}}
{{-- </a>--}}
<a class="btn btn-primary" href="{{ route('web.admin.users.edit', ['userId' => $id]) }}" data-toggle="tooltip"
title="Edit">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger" href="#" data-toggle="modal" data-target="#delete{{$id}}">
<i class="fas fa-trash"></i>
</a>
</div>
<div class="modal fade" id="delete{{ $id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Delete User?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Delete" below if you want to delete the user with id of {{ $id }}.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<form method="POST" action="{{ route('web.admin.users.delete', ['userId' => $id]) }}">
@method('DELETE')
@csrf
<button class="btn btn-danger" type="submit" data-toggle="tooltip" title="Delete">
Delete
</button>
</form>
</div>
</div>
</div>
</div>
......@@ -7,3 +7,7 @@
@if(null !== request()->session()->get('message'))
<div class="alert alert-info"> {{ request()->session()->get('message') }}</div>
@endif
@if(null !== request()->session()->get('error'))
<div class="alert alert-danger"> {{ request()->session()->get('error') }}</div>
@endif
......@@ -6,6 +6,7 @@ use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Web\Admin\HomeController;
use App\Http\Controllers\Web\Admin\LoginController;
use App\Http\Controllers\Web\Admin\DoorsController;
use App\Http\Controllers\Web\Admin\UsersController;
/*
|--------------------------------------------------------------------------
......@@ -65,5 +66,17 @@ Route::name('web.')->middleware(['auth:api'])->group(static function () {
Route::get('/{doorId}', [DoorsController::class, 'schedule'])->name('schedule');
Route::post('/{doorId}/regenerate-token', [DoorsController::class, 'regenerateToken'])->name('regenerate');
});
Route::name('users.')
->prefix('users')
->middleware('can:manage-users')
->group(static function () {
Route::get('/', [UsersController::class, 'index'])->name('index');
Route::view('/create', 'admin.entities.user')->name('build');
Route::post('/', [UsersController::class, 'create'])->name('create');
Route::get('/{userId}/edit', [UsersController::class, 'edit'])->name('edit');
Route::put('/{userId}', [UsersController::class, 'update'])->name('update');
Route::delete('/{userId}', [UsersController::class, 'delete'])->name('delete');
});
});
});
......@@ -16,7 +16,8 @@ use Source\Entities\Schedule;
abstract class BasePresenter
{
public const HUMAN_DATE_FORMAT = 'M j, Y H:i:s';
public const HUMAN_DAY_FORMAT = 'M j';
public const HUMAN_DAY_FORMAT = 'M j, Y';
public const DAY_FORMAT = 'Y-m-d';
/**
* @param Carbon|null $datetime
......
<?php
namespace Source\UseCases\Users\CreateUser;
use Source\UseCases\BasePresenter;
class WebPresenter extends BasePresenter implements Presenter
{
protected array $viewModel = [];
/** @inheritDoc */
public function present(ResponseModel $responseModel): void
{
$this->viewModel['message'] = 'Successfully created the user.';
}
/** @inheritDoc */
public function getViewModel(): array
{
return $this->viewModel;
}
}
......@@ -13,15 +13,13 @@ class WebPresenter extends BasePresenter implements Presenter
{
$user = $responseModel->getUser();
$this->viewModel['user'] = [
'Id' => $user->getId(),
'First Name' => $user->getFirstName(),
'Last Name' => $user->getLastName(),
'Full Name' => $user->getDisplayName(),
'Employee Id' => $user->getEmplid() ?? 'No Employee Id Set',
'Email' => $user->getEmail(),
'Expires At' => self::formatDateTime($user->getExpiresAt(), self::HUMAN_DATE_FORMAT) ?? 'Never Expires',
'Created At' => self::formatDateTime($user->getCreatedAt(), self::HUMAN_DATE_FORMAT) ?? 'Never',
'Updated At' => self::formatDateTime($user->getUpdatedAt(), self::HUMAN_DATE_FORMAT) ?? 'Never',
'id' => $user->getId(),
'first_name' => $user->getFirstName(),
'last_name' => $user->getLastName(),
'display_name' => $user->getDisplayName(),
'emplid' => $user->getEmplid(),
'email' => $user->getEmail(),
'expires_at' => self::formatDateTime($user->getExpiresAt(), self::DAY_FORMAT),
];
}
......
......@@ -15,7 +15,7 @@ class APIPresenter extends BasePresenter implements Presenter
/** @inheritDoc */
public function present(ResponseModel $responseModel): void
{
$this->users = array_map(fn (User $user): array => self::formatPartialUser($user), $responseModel->getUsers());
$this->users = array_map(fn(User $user): array => self::formatPartialUser($user), $responseModel->getUsers());
}
/** @inheritDoc */
......
<?php
namespace Source\UseCases\Users\GetUsers;
use Source\Entities\User;
use Source\Sanitize\Paginates;
use Source\UseCases\BasePresenter;
class WebPresenter extends BasePresenter implements Presenter
{
use Paginates;
protected array $users = [];
/** @inheritDoc */
public function present(ResponseModel $responseModel): void
{
$this->users = array_map(static function (User $user): array {
return [
'id' => $user->getId(),
'display_name' => $user->getDisplayName(),
'emplid' => $user->getEmplid(),
'email' => $user->getEmail(),
'expires_at' => self::formatDateTime($user->getExpiresAt(), self::HUMAN_DAY_FORMAT),
];
}, $responseModel->getUsers());
}
/** @inheritDoc */
public function getViewModel(array $appends = []): array
{
return [
'users' => $this->webPaginate($this->users, $appends),