Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 69 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
GetReportRequest | |
0.00% |
0 / 69 |
|
0.00% |
0 / 4 |
1056 | |
0.00% |
0 / 1 |
authorize | |
0.00% |
0 / 54 |
|
0.00% |
0 / 1 |
650 | |||
rules | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
prepareForValidation | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
30 | |||
getIdsAsArray | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace App\Http\Requests\v2\Reports; |
4 | |
5 | use App\Http\Models\Admin\CompanyGroup; |
6 | use App\Http\Models\Auth\Role; |
7 | use App\Http\Models\Auth\User; |
8 | use Illuminate\Foundation\Http\FormRequest; |
9 | |
10 | class GetReportRequest extends FormRequest |
11 | { |
12 | /** |
13 | * Determine if the user is authorized to make this request. |
14 | * |
15 | * @return bool |
16 | */ |
17 | public function authorize(): bool |
18 | { |
19 | $user = $this->user(); |
20 | $roles = $user->roles(); |
21 | |
22 | // 1. VENGRESO_ADMIN can do anything. |
23 | if (in_array(Role::VENGRESO_ADMIN, $roles)) { |
24 | return true; |
25 | } |
26 | |
27 | $isCmc = $this->input('cmc', false); |
28 | if ($isCmc && !in_array(Role::VENGRESO_ADMIN, $roles)) { |
29 | return false; |
30 | } |
31 | |
32 | // All other roles must belong to a company. |
33 | $userCompanyId = $user->company_id; |
34 | if (empty($userCompanyId)) { |
35 | return false; |
36 | } |
37 | |
38 | // 2. GLOBAL_ADMIN validation |
39 | if (in_array(Role::GLOBAL_ADMIN, $roles)) { |
40 | // They can only see data within their own company. |
41 | $requestedCompanyIds = $this->getIdsAsArray('company_ids'); |
42 | |
43 | // If they request specific companies, all must match their own. |
44 | if (!empty($requestedCompanyIds)) { |
45 | $unauthorizedIds = array_diff($requestedCompanyIds, [$userCompanyId]); |
46 | return empty($unauthorizedIds); // True if no unauthorized IDs were requested. |
47 | } |
48 | |
49 | // If no company is specified, it's allowed. Controller will scope. |
50 | return true; |
51 | } |
52 | |
53 | // 3. GROUP_ADMIN or REPORTING_ADMIN validation |
54 | if (in_array(Role::GROUP_ADMIN, $roles) || in_array(Role::REPORTING_ADMIN, $roles)) { |
55 | // First, ensure they are not trying to access other companies' data. |
56 | $requestedCompanyIds = $this->getIdsAsArray('company_ids'); |
57 | if (!empty($requestedCompanyIds)) { |
58 | $unauthorizedIds = array_diff($requestedCompanyIds, [$userCompanyId]); |
59 | if (!empty($unauthorizedIds)) { |
60 | return false; // Requesting companies they don't belong to. |
61 | } |
62 | } |
63 | |
64 | $requestedGroupIds = $this->getIdsAsArray('group_ids'); |
65 | $requestedSubgroupIds = $this->getIdsAsArray('subgroup_ids'); |
66 | $requestedUserIds = $this->getIdsAsArray('user_ids'); |
67 | |
68 | // If they request specific groups, validate them. |
69 | if (!empty($requestedGroupIds)) { |
70 | $groups = CompanyGroup::whereIn('id', $requestedGroupIds)->get(); |
71 | if ($groups->count() !== count($requestedGroupIds)) { |
72 | return false; // An invalid group ID was requested. |
73 | } |
74 | foreach ($groups as $group) { |
75 | if (!in_array($user->id, $group->admins ?? [])) { |
76 | return false; // Not an admin of this group. |
77 | } |
78 | } |
79 | } |
80 | |
81 | // If they request specific groups, validate them. |
82 | if (!empty($requestedSubgroupIds)) { |
83 | $groups = CompanyGroup::whereIn('id', $requestedSubgroupIds)->get(); |
84 | if ($groups->count() !== count($requestedSubgroupIds)) { |
85 | return false; // An invalid group ID was requested. |
86 | } |
87 | foreach ($groups as $group) { |
88 | if (!in_array($user->id, $group->admins ?? [])) { |
89 | return false; // Not an admin of this group. |
90 | } |
91 | } |
92 | } |
93 | |
94 | // If they request specific users, validate them. |
95 | if (!empty($requestedUserIds)) { |
96 | $managedGroupIds = CompanyGroup::where('company_id', $userCompanyId) |
97 | ->where('admins', $user->id) |
98 | ->pluck('id') |
99 | ->all(); |
100 | |
101 | if (empty($managedGroupIds)) { |
102 | return false; // This admin manages no groups, so they can't view any users. |
103 | } |
104 | |
105 | $usersToValidate = User::whereIn('id', $requestedUserIds)->get(); |
106 | if ($usersToValidate->count() !== count($requestedUserIds)) { |
107 | return false; // An invalid user ID was requested. |
108 | } |
109 | |
110 | foreach ($usersToValidate as $userToValidate) { |
111 | // This check assumes a user belongs to one group via `group_id`. |
112 | // If a user can belong to many groups, this check needs to be adapted. |
113 | if (!isset($userToValidate->group_id) || !in_array($userToValidate->group_id, $managedGroupIds)) { |
114 | return false; // This user is not in a group the admin manages. |
115 | } |
116 | } |
117 | } |
118 | |
119 | return true; // All checks passed. |
120 | } |
121 | |
122 | // If user has no specific admin role, deny access. |
123 | return false; |
124 | } |
125 | |
126 | /** |
127 | * Get the validation rules that apply to the request. |
128 | * |
129 | * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> |
130 | */ |
131 | public function rules(): array |
132 | { |
133 | return [ |
134 | 'cmc' => 'sometimes|boolean', |
135 | 'from' => 'sometimes|date', |
136 | 'to' => 'sometimes|date|after_or_equal:from', |
137 | 'company_ids' => 'sometimes|string', |
138 | 'group_ids' => 'sometimes|string', |
139 | 'subgroup_ids' => 'sometimes|string', |
140 | 'user_ids' => 'sometimes|string', |
141 | ]; |
142 | } |
143 | |
144 | /** |
145 | * Prepare the data for validation. |
146 | * |
147 | * @return void |
148 | */ |
149 | protected function prepareForValidation() |
150 | { |
151 | $user = $this->user(); |
152 | |
153 | // If a non-super-admin makes a request without specifying companyIds, |
154 | // we automatically scope the request to their own company. |
155 | if ($user && !in_array(Role::VENGRESO_ADMIN, $user->roles()) && !$this->has('companyIds') && $user->company_id) { |
156 | $this->merge([ |
157 | 'companyIds' => $user->company_id, |
158 | ]); |
159 | } |
160 | } |
161 | |
162 | /** |
163 | * Helper method to process comma-separated ID strings from the request. |
164 | * |
165 | * @param string $key |
166 | * @return array |
167 | */ |
168 | private function getIdsAsArray(string $key): array |
169 | { |
170 | return array_values(array_filter(explode(',', $this->input($key, '')))); |
171 | } |
172 | } |