Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
41.46% |
34 / 82 |
|
16.67% |
3 / 18 |
CRAP | |
0.00% |
0 / 1 |
BaseController | |
41.46% |
34 / 82 |
|
16.67% |
3 / 18 |
280.71 | |
0.00% |
0 / 1 |
sendResponse | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
sendError | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createUser | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
updateUserPassword | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
getLoggedInUserId | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
__validateJson | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
4 | |||
__validateContentTypeApplicationJson | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
createPaginationFromOrm | |
83.33% |
10 / 12 |
|
0.00% |
0 / 1 |
3.04 | |||
saltHash | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
__validateSaltHash | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
__dateMidnightZeroOne | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
__dateMidnightZeroZero | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
__dateElevenFiftyNine | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
__getAllDates | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
__validYYYYMMDDFormat | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
__validateDateTime | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
__validateAndExtractPaginationData | |
75.00% |
6 / 8 |
|
0.00% |
0 / 1 |
5.39 | |||
__getMe | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace App\Http\Controllers\api; |
4 | |
5 | use Illuminate\Http\Request; |
6 | use Illuminate\Http\JsonResponse; |
7 | use App\Http\Controllers\Controller as Controller; |
8 | use Validator; |
9 | use App\Models\User; |
10 | use App\Models\Role; |
11 | |
12 | class BaseController extends Controller |
13 | { |
14 | /** |
15 | * success response method. |
16 | * |
17 | * @param Int $status The HTTP status code of the response, ie 200 |
18 | * @param Mixed $data The data object to return under 'data' |
19 | * @param Array $hateoas An array of HATEOAS data, optional |
20 | * @return JsonResponse |
21 | */ |
22 | public function sendResponse(int $status, $data, array $hateoas = array()):JsonResponse |
23 | { |
24 | $response = [ |
25 | 'data' => $data, |
26 | ]; |
27 | |
28 | if (count($hateoas) > 0) { |
29 | $response['links'] = $hateoas; |
30 | } |
31 | |
32 | return response()->json($response, $status); |
33 | } // sendResponse |
34 | |
35 | |
36 | /** |
37 | * return error response. |
38 | * |
39 | * @param Int $status |
40 | * @param Mixed $error |
41 | * @param Mixed $details |
42 | * @return JsonResponse |
43 | */ |
44 | public function sendError(int $status, $error, $details=null):JsonResponse |
45 | { |
46 | $response = [ |
47 | 'error' => $error, |
48 | 'details' => $details, |
49 | ]; |
50 | |
51 | return response()->json($response, $status); |
52 | } // sendError |
53 | |
54 | |
55 | /** |
56 | * Creates a login user of a given role |
57 | * |
58 | * @param Array $userData ["name", "email", "password", "c_password"] |
59 | * @param Int $roleId |
60 | * @return Int The user id |
61 | */ |
62 | protected function createUser(array $userData, Int $roleId = 2):Int |
63 | { |
64 | $userData['password'] = bcrypt($userData['password']); |
65 | |
66 | // did you run php artisan passport:install? |
67 | try { |
68 | $user = User::create($userData); |
69 | //$user->createToken('MyApp')->accessToken; |
70 | //$user->role_id = $roleId; |
71 | $user->save(); |
72 | return $user->id; |
73 | } |
74 | // catch duplicate entry |
75 | catch (\Illuminate\Database\QueryException $e) { |
76 | return -1; |
77 | } |
78 | } // createUser |
79 | |
80 | |
81 | /** |
82 | * Updates the login password for a user. Used with putCustomersCorporateContact. |
83 | * |
84 | * @param string $password |
85 | * @return Boolean |
86 | */ |
87 | protected function updateUserPassword(string $email, string $password) |
88 | { |
89 | $enc = bcrypt($password); |
90 | |
91 | // did you run php artisan passport:install? |
92 | try { |
93 | /** |
94 | * Update user login account |
95 | */ |
96 | $user = User::where('email', $email)->first(); |
97 | if (!$user) { |
98 | return false; |
99 | } |
100 | $user->password = $enc; |
101 | $user->save(); |
102 | return true; |
103 | } |
104 | // catch any errors |
105 | catch (\Illuminate\Database\QueryException $e) { |
106 | return false; |
107 | } |
108 | } // updateUserPassword |
109 | |
110 | |
111 | /** |
112 | * Tests if the role of the logged-in user is the same as the role passed as arg |
113 | * |
114 | * Modified: also returns true if the user is 'admin' |
115 | * |
116 | * Roles are stored as env constants in .env where they are mapped to the name in the `roles` table. |
117 | * |
118 | * @param String $role The role of the user, ie 'installer', 'lead_manager' or 'admin' |
119 | * @return bool |
120 | * @author gbh |
121 | protected function permissionsEqual(string $role):bool |
122 | { |
123 | $role_id = Role::where('name', config('app.roles.'.$role))->get()->pluck('id')[0]; // @not-phpstan-ignore-line |
124 | $admin_id = Role::where('name', config('app.roles.admin'))->get()->pluck('id')[0]; // @not-phpstan-ignore-line |
125 | return (auth()->guard('api')->user()->role_id == $role_id || auth()->guard('api')->user()->role_id == $admin_id); |
126 | } |
127 | */ |
128 | |
129 | |
130 | /** |
131 | * Tests if the role of the logged-in user is exactly the same as role arg, excluding admin. |
132 | * |
133 | * Roles are stored as env constants in .env where they are mapped to the name in the `roles` table. |
134 | * |
135 | * @param String $role The role of the user, ie 'installer', 'lead_manager' or 'admin' |
136 | * @return bool |
137 | * @author arn |
138 | protected function permissionsExactly(string $role):bool |
139 | { |
140 | $role_id = Role::where('name', config('app.roles.'.$role))->get()->pluck('id')[0]; // @not-phpstan-ignore-line |
141 | return auth()->guard('api')->user()->role_id == $role_id; |
142 | } |
143 | */ |
144 | |
145 | |
146 | /** |
147 | * Tests if the role of the logged-in user is the same or greater than the role passed as arg |
148 | * |
149 | * Roles are stored as env constants in .env where they are mapped to the name in the `roles` table. |
150 | * |
151 | * @param String $role The role of the user, ie 'employee', 'support' or 'admin' |
152 | * @return bool |
153 | * @author gbh |
154 | protected function permissionsAtLeast(string $role) |
155 | { |
156 | $role_id = Role::where('name', config('app.roles.'.$role))->get()->pluck('id')[0]; // @not-phpstan-ignore-line |
157 | return (int)auth()->guard('api')->user()->role_id >= $role_id; |
158 | } |
159 | */ |
160 | |
161 | /** |
162 | * Get user id of logged-in user. |
163 | * |
164 | * @return Mixed Int user_id or false |
165 | * @author arn |
166 | */ |
167 | protected function getLoggedInUserId() |
168 | { |
169 | $currentUser = auth()->guard('api')->user(); |
170 | |
171 | /** |
172 | * If authenticated user is not found, do not authenticate. |
173 | */ |
174 | if (!$currentUser) { |
175 | return false; |
176 | } |
177 | |
178 | return $currentUser->id; |
179 | } // getLoggedInUserId |
180 | |
181 | |
182 | /** |
183 | * Validates a json string against a set of Laravel validation rules. |
184 | * |
185 | * @note Only flat json at this point |
186 | * |
187 | * @param Array $rules The Laravel validator ruleset to validate against |
188 | * @param Request $request The request object laravel injects into the controller |
189 | * @return mixed `boolean` true on success, `Array` on failure |
190 | */ |
191 | protected function __validateJson(array $rules, Request $request) |
192 | { |
193 | $requestContent = $request->getContent(); |
194 | $data = json_decode($requestContent, true); |
195 | $data = $data ? $data : []; |
196 | $validator = Validator::make($data, $rules); |
197 | |
198 | if ($validator->passes()) { |
199 | return true; |
200 | } else { |
201 | $errors = $validator->errors(); |
202 | $errorArray = []; |
203 | foreach ($errors->getMessages() as $key => $message) { |
204 | $errorArray[$key] = $message; |
205 | } |
206 | return $errorArray; |
207 | } |
208 | } //validateJson |
209 | |
210 | |
211 | /** |
212 | * Returns true if the header for Content-Type is 'application/json' |
213 | * |
214 | * @param Request $request |
215 | * @return bool |
216 | */ |
217 | protected function __validateContentTypeApplicationJson(Request $request):bool |
218 | { |
219 | return strtolower($request->headers->get('Content-Type')) == "application/json"; |
220 | } // validateContentTypeApplicationJson |
221 | |
222 | |
223 | /** |
224 | * Makes a nice hateoas array from LengthAwarePaginator collection |
225 | * |
226 | * @param \Illuminate\Contracts\Pagination\LengthAwarePaginator $paginationCollection The return collection from Model::paginate() |
227 | * @return Array |
228 | */ |
229 | protected function createPaginationFromOrm(\Illuminate\Contracts\Pagination\LengthAwarePaginator $paginationCollection) |
230 | { |
231 | $hateoas = []; |
232 | if ($paginationCollection->hasMorePages()) { |
233 | $hateoas['next_page'] = $paginationCollection->nextPageUrl(). |
234 | "&size=". |
235 | $paginationCollection->count(); |
236 | } |
237 | if ($paginationCollection->previousPageUrl()) { |
238 | $hateoas['previous_page'] = $paginationCollection->previousPageUrl(). |
239 | "&size=". |
240 | $paginationCollection->count(); |
241 | } |
242 | $hateoas['has_more'] = $paginationCollection->hasMorePages(); |
243 | $hateoas['current_page'] = $paginationCollection->currentPage(); |
244 | $hateoas['last_page'] = $paginationCollection->lastPage(); |
245 | $hateoas['current_size'] = $paginationCollection->perPage(); |
246 | |
247 | return $hateoas; |
248 | } // createPaginationFromOrm |
249 | |
250 | |
251 | /** |
252 | * Hashes a value with our configured secret_salt |
253 | * |
254 | * @param String $toHash The value to hash |
255 | * @return String |
256 | */ |
257 | protected function saltHash(String $toHash):String |
258 | { |
259 | return md5($toHash.config('app.secret_salt')); |
260 | } // saltHash |
261 | |
262 | |
263 | /** |
264 | * Tests if the hash $hash is valid for the value $value |
265 | * |
266 | * @param String $value |
267 | * @param String $hash |
268 | * @return boolean |
269 | */ |
270 | protected function __validateSaltHash(String $value, String $hash):bool |
271 | { |
272 | return md5($value.config('app.secret_salt')) == $hash; |
273 | } // validateSaltHash |
274 | |
275 | |
276 | |
277 | /** |
278 | * Sets the time of a date string to midnight plus one second. |
279 | * |
280 | * eg. '2020-02-23 13:45:23' => '2020-02-23 00:00:01' |
281 | * |
282 | * @param String $date |
283 | * @return String |
284 | */ |
285 | protected function __dateMidnightZeroOne(String $date):String |
286 | { |
287 | $dateObj = new \DateTime($date); |
288 | $dateObj->setTime(00, 00, 01); |
289 | return $dateObj->format('Y-m-d H:i:s'); |
290 | } |
291 | |
292 | /** |
293 | * Sets the time of a date string to midnight |
294 | * |
295 | * eg. '2020-02-23 13:45:23' => '2020-02-23 00:00:00' |
296 | * |
297 | * @param String $date |
298 | * @return String |
299 | */ |
300 | protected function __dateMidnightZeroZero(String $date):String |
301 | { |
302 | $dateObj = new \DateTime($date); |
303 | $dateObj->setTime(00, 00, 00); |
304 | return $dateObj->format('Y-m-d H:i:s'); |
305 | } |
306 | |
307 | |
308 | /** |
309 | * Sets the time of a date string to 11:59:59 |
310 | * |
311 | * eg. '2020-02-23 13:45:23' => '2020-02-23 23:59:59' |
312 | * |
313 | * @param String $date |
314 | * @return String |
315 | */ |
316 | protected function __dateElevenFiftyNine(String $date):String |
317 | { |
318 | $dateObj = new \DateTime($date); |
319 | $dateObj->setTime(23, 59, 59); |
320 | return $dateObj->format('Y-m-d H:i:s'); |
321 | } |
322 | |
323 | |
324 | /** |
325 | * Get an array of all dates as YYYY-MM-DD between start date and end date |
326 | * |
327 | * @param String $startdate |
328 | * @param String $enddate |
329 | * @return Array |
330 | */ |
331 | protected function __getAllDates(String $startdate, String $enddate):array |
332 | { |
333 | $begin = new \DateTime($startdate); |
334 | $end = new \DateTime($enddate); |
335 | $end = $end->modify('+1 day'); |
336 | $interval = new \DateInterval('P1D'); |
337 | $daterange = new \DatePeriod($begin, $interval, $end); |
338 | |
339 | $returnableDateRange = []; |
340 | foreach ($daterange as $d) { |
341 | $returnableDateRange[] = $d->format("Y-m-d"); |
342 | } |
343 | |
344 | return $returnableDateRange; |
345 | } // __getAllDates |
346 | |
347 | |
348 | /** |
349 | * Validates that a string is in yyyy-mm-dd format |
350 | * |
351 | * @param String $date The string to validate |
352 | * @return boolean |
353 | */ |
354 | public function __validYYYYMMDDFormat($date):bool |
355 | { |
356 | $format = 'Y-m-d'; |
357 | $d = \DateTime::createFromFormat($format, $date); |
358 | return $d && $d->format($format) == $date; |
359 | } // __validYYYYMMDDFormat |
360 | |
361 | |
362 | /** |
363 | * Validates that a string is in yyyy-mm-dd h:i:s format |
364 | */ |
365 | public function __validateDateTime(String $date, String $format = 'Y-m-d H:i:s'):bool |
366 | { |
367 | $d = \DateTime::createFromFormat($format, $date); |
368 | return $d && $d->format($format) == $date; |
369 | } // __validateDateTime |
370 | |
371 | |
372 | /** |
373 | * Validate pagination query string in a request. |
374 | * This will return the object [ 'page' => A, 'size' => B ] on a valid request, |
375 | * or an error response on failure. |
376 | * |
377 | * @return Mixed |
378 | */ |
379 | protected function __validateAndExtractPaginationData(Request $request):array |
380 | { |
381 | $page = $request->query('page') !== null ? (int)$request->query('page') : config('app.pagination.default_page_number'); |
382 | $size = $request->query('size') !== null ? (int)$request->query('size') : config('app.pagination.default_page_size'); |
383 | |
384 | if ($page < 1) { |
385 | $page = 1; |
386 | } |
387 | |
388 | if ($size < 1) { |
389 | $size = 1; |
390 | } |
391 | |
392 | $request->page = $page; |
393 | |
394 | return [ |
395 | 'page' => $page, |
396 | 'size' => $size |
397 | ]; |
398 | } // __validateAndExtractPaginationData |
399 | |
400 | |
401 | /** |
402 | * Selects and returns the current session user |
403 | * |
404 | * @return User |
405 | */ |
406 | protected function __getMe():User |
407 | { |
408 | $user = User::whereMe()->first(); |
409 | return $user; |
410 | } |
411 | } // BaseController |