Skip to content

Commit

Permalink
#190 - Permissions (#353)
Browse files Browse the repository at this point in the history
* #177 - Delegations

* Linter fixes

* Tests

* #190 - Permissions

* CR fix

* CR fixes

* Tests

* CR fix

* Notification permissions

* #190 - padding fix

* CR fixes

---------

Co-authored-by: EwelinaSkrzypacz <[email protected]>
  • Loading branch information
mlencki and EwelinaSkrzypacz authored Sep 25, 2023
1 parent 16d2277 commit 6a0e723
Show file tree
Hide file tree
Showing 61 changed files with 1,243 additions and 286 deletions.
21 changes: 0 additions & 21 deletions app/Architecture/Providers/AuthServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
namespace Toby\Architecture\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Toby\Domain\Enums\Role;
use Toby\Domain\Policies\KeyPolicy;
use Toby\Domain\Policies\VacationRequestPolicy;
use Toby\Eloquent\Models\Key;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;

class AuthServiceProvider extends ServiceProvider
Expand All @@ -19,22 +16,4 @@ class AuthServiceProvider extends ServiceProvider
VacationRequest::class => VacationRequestPolicy::class,
Key::class => KeyPolicy::class,
];

public function boot(): void
{
Gate::before(function (User $user) {
if ($user->role === Role::Administrator) {
return true;
}
});

Gate::define("manageUsers", fn(User $user): bool => $user->role === Role::AdministrativeApprover);
Gate::define("manageHolidays", fn(User $user): bool => $user->role === Role::AdministrativeApprover);
Gate::define("manageVacationLimits", fn(User $user): bool => $user->role === Role::AdministrativeApprover);
Gate::define("generateTimesheet", fn(User $user): bool => $user->role === Role::AdministrativeApprover);
Gate::define("listMonthlyUsage", fn(User $user): bool => $user->role === Role::AdministrativeApprover);
Gate::define("manageResumes", fn(User $user): bool => $user->role === Role::TechnicalApprover);
Gate::define("manageBenefits", fn(User $user): bool => $user->role === Role::AdministrativeApprover);
Gate::define("seePendingRequests", fn(User $user): bool => $user->role === Role::AdministrativeApprover || $user->role === Role::TechnicalApprover);
}
}
17 changes: 17 additions & 0 deletions app/Domain/Actions/SyncUserPermissionsWithRoleAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Toby\Domain\Actions;

use Toby\Eloquent\Models\User;

class SyncUserPermissionsWithRoleAction
{
public function execute(User $user): User
{
$user->syncPermissions($user->role->permissions());

return $user;
}
}
23 changes: 23 additions & 0 deletions app/Domain/Actions/UpdateUserPermissionsAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Toby\Domain\Actions;

use Toby\Eloquent\Models\User;

class UpdateUserPermissionsAction
{
public function execute(User $user, array $permissions): User
{
foreach ($permissions as $permission => $value) {
if ($value) {
$user->givePermissionTo($permission);
} else {
$user->revokePermissionTo($permission);
}
}

return $user;
}
}
7 changes: 2 additions & 5 deletions app/Domain/Actions/VacationRequest/ApproveAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Toby\Domain\Actions\VacationRequest;

use Toby\Domain\Enums\Role;
use Spatie\Permission\Models\Permission;
use Toby\Domain\Events\VacationRequestChanged;
use Toby\Domain\Notifications\VacationRequestStatusChangedNotification;
use Toby\Domain\VacationRequestStateManager;
Expand Down Expand Up @@ -35,10 +35,7 @@ public function execute(VacationRequest $vacationRequest, ?User $user = null): v

protected function notify(VacationRequest $vacationRequest): void
{
$users = User::query()
->where("id", "!=", $vacationRequest->user->id)
->whereIn("role", [Role::TechnicalApprover, Role::AdministrativeApprover, Role::Administrator])
->get();
$users = Permission::findByName("receiveVacationRequestStatusChangedNotification")->users()->get();

foreach ($users as $user) {
$user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $user));
Expand Down
7 changes: 2 additions & 5 deletions app/Domain/Actions/VacationRequest/CancelAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Toby\Domain\Actions\VacationRequest;

use Toby\Domain\Enums\Role;
use Spatie\Permission\Models\Permission;
use Toby\Domain\Events\VacationRequestChanged;
use Toby\Domain\Notifications\VacationRequestStatusChangedNotification;
use Toby\Domain\VacationRequestStateManager;
Expand Down Expand Up @@ -35,10 +35,7 @@ public function execute(VacationRequest $vacationRequest, User $user): void

protected function notify(VacationRequest $vacationRequest): void
{
$users = User::query()
->where("id", "!=", $vacationRequest->user->id)
->whereIn("role", [Role::TechnicalApprover, Role::AdministrativeApprover, Role::Administrator])
->get();
$users = Permission::findByName("receiveVacationRequestStatusChangedNotification")->users()->get();

foreach ($users as $user) {
$user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $user));
Expand Down
6 changes: 3 additions & 3 deletions app/Domain/Actions/VacationRequest/RejectAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Toby\Domain\Actions\VacationRequest;

use Toby\Domain\Enums\Role;
use Spatie\Permission\Models\Permission;
use Toby\Domain\Events\VacationRequestChanged;
use Toby\Domain\Notifications\VacationRequestStatusChangedNotification;
use Toby\Domain\VacationRequestStateManager;
Expand All @@ -28,9 +28,9 @@ public function execute(VacationRequest $vacationRequest, User $user): void

protected function notify(VacationRequest $vacationRequest): void
{
$users = User::query()
$users = Permission::findByName("receiveVacationRequestStatusChangedNotification")
->users()
->where("id", "!=", $vacationRequest->user->id)
->whereIn("role", [Role::TechnicalApprover, Role::AdministrativeApprover, Role::Administrator])
->get();

foreach ($users as $user) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Toby\Domain\Actions\VacationRequest;

use Toby\Domain\Enums\Role;
use Spatie\Permission\Models\Permission;
use Toby\Domain\Notifications\VacationRequestWaitsForApprovalNotification;
use Toby\Domain\VacationRequestStateManager;
use Toby\Domain\VacationTypeConfigRetriever;
Expand All @@ -24,16 +24,18 @@ public function execute(VacationRequest $vacationRequest): void
$this->stateManager->waitForAdministrative($vacationRequest);

if ($this->configRetriever->isVacation($vacationRequest->type)) {
$this->notifyAdminApprovers($vacationRequest);
$this->notifyAuthorizedUsers($vacationRequest);
}
}

protected function notifyAdminApprovers(VacationRequest $vacationRequest): void
protected function notifyAuthorizedUsers(VacationRequest $vacationRequest): void
{
$users = User::query()
->whereIn("role", [Role::AdministrativeApprover, Role::Administrator])
$users = Permission::findByName("receiveVacationRequestWaitsForApprovalNotification")
->users()
->get();

$users = $users->filter(fn(User $user): bool => $user->can("acceptAsAdminApprover", $vacationRequest));

foreach ($users as $user) {
$user->notify(new VacationRequestWaitsForApprovalNotification($vacationRequest, $user));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Toby\Domain\Actions\VacationRequest;

use Toby\Domain\Enums\Role;
use Spatie\Permission\Models\Permission;
use Toby\Domain\Notifications\VacationRequestWaitsForApprovalNotification;
use Toby\Domain\VacationRequestStateManager;
use Toby\Domain\VacationTypeConfigRetriever;
Expand All @@ -30,10 +30,12 @@ public function execute(VacationRequest $vacationRequest): void

protected function notifyTechApprovers(VacationRequest $vacationRequest): void
{
$users = User::query()
->whereIn("role", [Role::TechnicalApprover, Role::Administrator])
$users = Permission::findByName("receiveVacationRequestWaitsForApprovalNotification")
->users()
->get();

$users = $users->filter(fn(User $user): bool => $user->can("acceptAsTechApprover", $vacationRequest));

foreach ($users as $user) {
$user->notify(new VacationRequestWaitsForApprovalNotification($vacationRequest, $user));
}
Expand Down
3 changes: 1 addition & 2 deletions app/Domain/DashboardAggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Toby\Eloquent\Models\Holiday;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\Vacation;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Eloquent\Models\YearPeriod;
use Toby\Infrastructure\Http\Resources\BirthdayResource;
use Toby\Infrastructure\Http\Resources\HolidayResource;
Expand Down Expand Up @@ -85,7 +84,7 @@ public function aggregateCalendarData(User $user, YearPeriod $yearPeriod): array

public function aggregateVacationRequests(User $user, YearPeriod $yearPeriod): JsonResource
{
if ($user->can("listAll", VacationRequest::class)) {
if ($user->can("listAllRequests")) {
$vacationRequests = $yearPeriod->vacationRequests()
->states(VacationRequestStatesRetriever::waitingForUserActionStates($user))
->latest("updated_at")
Expand Down
5 changes: 5 additions & 0 deletions app/Domain/Enums/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@ public static function casesToSelect(): array
],
)->toArray();
}

public function permissions(): array
{
return config("permission.permission_roles")[$this->value];
}
}
8 changes: 1 addition & 7 deletions app/Domain/Policies/KeyPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,17 @@

namespace Toby\Domain\Policies;

use Toby\Domain\Enums\Role;
use Toby\Eloquent\Models\Key;
use Toby\Eloquent\Models\User;

class KeyPolicy
{
public function manage(User $user): bool
{
return $user->role === Role::AdministrativeApprover;
}

public function give(User $user, Key $key): bool
{
if ($key->user()->is($user)) {
return true;
}

return $user->role === Role::AdministrativeApprover;
return $user->hasPermissionTo("manageKeys");
}
}
25 changes: 8 additions & 17 deletions app/Domain/Policies/VacationRequestPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Toby\Domain\Policies;

use Toby\Domain\Enums\Role;
use Toby\Domain\Enums\VacationType;
use Toby\Domain\States\VacationRequest\Created;
use Toby\Domain\States\VacationRequest\WaitingForAdministrative;
Expand All @@ -14,34 +13,25 @@

class VacationRequestPolicy
{
public function listAll(User $user): bool
{
return in_array($user->role, [Role::AdministrativeApprover, Role::TechnicalApprover], true);
}

public function createOnBehalfOfEmployee(User $user): bool
{
return $user->role === Role::AdministrativeApprover;
}

public function acceptAsAdminApprover(User $user): bool
{
return $user->role === Role::AdministrativeApprover;
return $user->hasPermissionTo("manageRequestsAsAdministrativeApprover");
}

public function acceptAsTechApprover(User $user): bool
{
return $user->role === Role::TechnicalApprover;
return $user->hasPermissionTo("manageRequestsAsTechnicalApprover");
}

public function skipFlow(User $user): bool
{
return $user->role === Role::AdministrativeApprover;
return $user->hasPermissionTo("manageRequestsAsAdministrativeApprover");
}

public function reject(User $user): bool
{
return in_array($user->role, [Role::AdministrativeApprover, Role::TechnicalApprover], true);
return $user->hasPermissionTo("manageRequestsAsAdministrativeApprover") ||
$user->hasPermissionTo("manageRequestsAsTechnicalApprover");
}

public function cancel(User $user, VacationRequest $vacationRequest): bool
Expand All @@ -58,7 +48,7 @@ public function cancel(User $user, VacationRequest $vacationRequest): bool
return true;
}

return $user->role === Role::AdministrativeApprover;
return $user->hasPermissionTo("manageRequestsAsAdministrativeApprover");
}

public function show(User $user, VacationRequest $vacationRequest): bool
Expand All @@ -67,6 +57,7 @@ public function show(User $user, VacationRequest $vacationRequest): bool
return true;
}

return in_array($user->role, [Role::TechnicalApprover, Role::AdministrativeApprover], true);
return $user->hasPermissionTo("manageRequestsAsAdministrativeApprover") ||
$user->hasPermissionTo("manageRequestsAsTechnicalApprover");
}
}
7 changes: 2 additions & 5 deletions app/Eloquent/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Spatie\Permission\Traits\HasRoles;
use Toby\Domain\Enums\EmploymentForm;
use Toby\Domain\Enums\Role;
use Toby\Domain\Notifications\Notifiable as NotifiableInterface;
Expand All @@ -34,6 +35,7 @@ class User extends Authenticatable implements NotifiableInterface
use HasFactory;
use Notifiable;
use SoftDeletes;
use HasRoles;

protected $guarded = [];
protected $casts = [
Expand Down Expand Up @@ -80,11 +82,6 @@ public function keys(): HasMany
return $this->hasMany(Key::class);
}

public function hasRole(Role $role): bool
{
return $this->role === $role;
}

public function hasVacationLimit(YearPeriod $yearPeriod): bool
{
return $this->vacationLimits()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Toby\Domain\Enums\Role;
use Spatie\Permission\Models\Permission;
use Toby\Domain\Notifications\UpcomingAndOverdueMedicalExamsNotification;
use Toby\Eloquent\Models\User;

Expand All @@ -17,9 +17,7 @@ class SendNotificationAboutUpcomingAndOverdueMedicalExams extends Command

public function handle(): void
{
$usersToNotify = User::query()
->whereIn("role", [Role::AdministrativeApprover])
->get();
$usersToNotify = Permission::findByName("receiveUpcomingAndOverdueMedicalExamsNotification")->users()->get();

$usersUpcomingMedicalExams = User::query()
->whereRelation("profile", "next_medical_exam_date", ">", Carbon::now())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Toby\Domain\Enums\Role;
use Spatie\Permission\Models\Permission;
use Toby\Domain\Notifications\UpcomingAndOverdueOhsTrainingNotification;
use Toby\Eloquent\Models\User;

Expand All @@ -17,9 +17,7 @@ class SendNotificationAboutUpcomingAndOverdueOhsTraining extends Command

public function handle(): void
{
$usersToNotify = User::query()
->whereIn("role", [Role::AdministrativeApprover])
->get();
$usersToNotify = Permission::findByName("receiveUpcomingAndOverdueOhsTrainingNotification")->users()->get();

$usersForUpcomingOhsTraining = User::query()
->whereRelation("profile", "next_ohs_training_date", ">", Carbon::now())
Expand Down
Loading

0 comments on commit 6a0e723

Please sign in to comment.