Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
84.48% covered (warning)
84.48%
49 / 58
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
AuthorizationService
84.48% covered (warning)
84.48%
49 / 58
57.14% covered (warning)
57.14%
4 / 7
22.65
0.00% covered (danger)
0.00%
0 / 1
 getRolesForUser
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 userHasRole
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getPrimaryRole
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCoachIdForUser
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 userCanAccessChild
81.82% covered (warning)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
5.15
 userCanAccessGroup
78.57% covered (warning)
78.57%
11 / 14
0.00% covered (danger)
0.00%
0 / 1
5.25
 userCanAccessSession
75.00% covered (warning)
75.00%
12 / 16
0.00% covered (danger)
0.00%
0 / 1
6.56
1<?php
2
3namespace App\Services;
4
5use App\Models\ChildModel;
6use App\Models\CoachModel;
7
8class AuthorizationService
9{
10    public function getRolesForUser(int $userId): array
11    {
12        $rows = db_connect()
13            ->table('user_roles')
14            ->select('roles.slug')
15            ->join('roles', 'roles.id = user_roles.role_id')
16            ->where('user_roles.user_id', $userId)
17            ->orderBy('roles.priority', 'ASC')
18            ->get()
19            ->getResultArray();
20
21        return array_values(array_map(static fn (array $row): string => $row['slug'], $rows));
22    }
23
24    /**
25     * @param array<int, string>|string $roles
26     */
27    public function userHasRole(int $userId, array|string $roles): bool
28    {
29        $roles = is_array($roles) ? $roles : [$roles];
30
31        return array_intersect($this->getRolesForUser($userId), $roles) !== [];
32    }
33
34    public function getPrimaryRole(int $userId): ?string
35    {
36        return $this->getRolesForUser($userId)[0] ?? null;
37    }
38
39    public function getCoachIdForUser(int $userId): ?int
40    {
41        $coach = model(CoachModel::class)
42            ->select('id')
43            ->where('user_id', $userId)
44            ->first();
45
46        return $coach['id'] ?? null;
47    }
48
49    public function userCanAccessChild(int $userId, int $childId): bool
50    {
51        if ($this->userHasRole($userId, 'admin')) {
52            return true;
53        }
54
55        if (! $this->userHasRole($userId, 'coach')) {
56            return false;
57        }
58
59        $coachId = $this->getCoachIdForUser($userId);
60        if ($coachId === null) {
61            return false;
62        }
63
64        $child = model(ChildModel::class)
65            ->select('primary_coach_id')
66            ->find($childId);
67
68        return $child !== null && (int) ($child['primary_coach_id'] ?? 0) === $coachId;
69    }
70
71    public function userCanAccessGroup(int $userId, int $groupId): bool
72    {
73        if ($this->userHasRole($userId, 'admin')) {
74            return true;
75        }
76
77        if (! $this->userHasRole($userId, 'coach')) {
78            return false;
79        }
80
81        $coachId = $this->getCoachIdForUser($userId);
82        if ($coachId === null) {
83            return false;
84        }
85
86        $group = db_connect()
87            ->table('academy_groups')
88            ->select('primary_coach_id')
89            ->where('id', $groupId)
90            ->get()
91            ->getRowArray();
92
93        return $group !== null && (int) ($group['primary_coach_id'] ?? 0) === $coachId;
94    }
95
96    public function userCanAccessSession(int $userId, int $sessionId): bool
97    {
98        if ($this->userHasRole($userId, 'admin')) {
99            return true;
100        }
101
102        if (! $this->userHasRole($userId, 'coach')) {
103            return false;
104        }
105
106        $coachId = $this->getCoachIdForUser($userId);
107        if ($coachId === null) {
108            return false;
109        }
110
111        $session = db_connect()
112            ->table('attendance_sessions')
113            ->select('academy_group_id, coach_id')
114            ->where('id', $sessionId)
115            ->get()
116            ->getRowArray();
117
118        if ($session === null) {
119            return false;
120        }
121
122        return (int) ($session['coach_id'] ?? 0) === $coachId || $this->userCanAccessGroup($userId, (int) $session['academy_group_id']);
123    }
124}