Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
RolePlayDeletionAuthTrait
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
2 / 2
8
100.00% covered (success)
100.00%
1 / 1
 assertCanActOn
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
6
 actorHasRole
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace App\Http\Services\RolePlay;
4
5use App\Http\Models\Auth\Role;
6use App\Http\Models\Auth\User;
7use Illuminate\Auth\Access\AuthorizationException;
8
9/**
10 * Cascade authorization helper for roleplay delete operations.
11 *
12 * Rules (in order):
13 *   1. A user with the VENGRESO_ADMIN role can act on any owner.
14 *   2. A user with the GLOBAL_ADMIN role can act on any owner whose
15 *      company_id matches the actor's company_id.
16 *   3. Any user can act on resources they own.
17 *
18 * If none of the above match, AuthorizationException is thrown.
19 */
20trait RolePlayDeletionAuthTrait
21{
22    /**
23     * @throws AuthorizationException
24     */
25    private function assertCanActOn(User $actor, string $ownerUserId, ?string $ownerCompanyId): void
26    {
27        if ((string) $actor->id === (string) $ownerUserId) {
28            return;
29        }
30
31        if ($this->actorHasRole($actor, Role::VENGRESO_ADMIN)) {
32            return;
33        }
34
35        if (
36            $ownerCompanyId !== null
37            && (string) $actor->company_id === (string) $ownerCompanyId
38            && $this->actorHasRole($actor, Role::GLOBAL_ADMIN)
39        ) {
40            return;
41        }
42
43        throw new AuthorizationException('You are not authorized to perform this action.');
44    }
45
46    private function actorHasRole(User $actor, string $role): bool
47    {
48        try {
49            return (bool) $actor->hasRole($role);
50        } catch (\Throwable) {
51            return false;
52        }
53    }
54}