-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApiAuthMiddleware.php
More file actions
114 lines (88 loc) · 3.93 KB
/
ApiAuthMiddleware.php
File metadata and controls
114 lines (88 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php
namespace App\Http\Middleware;
use App\Models\Application;
use App\Models\UsageLog;
use App\Models\WhatNowEntity;
use Carbon\Carbon;
use Closure;
use Illuminate\Support\Facades\Log;
class ApiAuthMiddleware extends BasicAuthMiddleware
{
public function handle($request, Closure $next)
{
$apiKey = $request->header('x-api-key');
$authHeader = $request->header('Authorization');
$isBasicAuth = $authHeader && str_starts_with($authHeader, 'Basic ');
if (!$apiKey && !$isBasicAuth) {
return response()->json(['error' => 'Authentication required. Provide API key or Basic auth'], 401);
}
if ($isBasicAuth) {
return parent::handle($request, $next);
}
if ($apiKey) {
$application = Application::query()->where('key', '=', $apiKey)->first();
if (!$application) {
return response()->json(['error' => 'Invalid API key'], 401);
}
if ($application->trashed() || !$application->is_active) {
return response()->json(['error' => 'Application is unavailable'], 403);
}
$canAccess = $this->canAccessRequestedVersion($request->path(), (array) $application->rules);
if (!$canAccess) {
return response()->json(['error' => 'Application is not allowed to access this API version'], 403);
}
$canAccessOrganisation = $this->canAccessOrganisation($request->path(), (array) $application->rules);
if (!$canAccessOrganisation) {
return response()->json(['error' => 'Application is not allowed to access this organisation'], 403);
}
$usageLog = new UsageLog;
$usageLog->application_id = $application->id;
$usageLog->method = $request->method();
$usageLog->endpoint = $request->path();
$usageLog->timestamp = Carbon::now()->toDateTimeString();
$usageLog->code_status = 200;
$usageLog->language = $request->input('language', false) ? $request->input('language', null) : $request->header('Accept-Language', null);
$usageLog->subnational = $request->input('subnational', null);
$usageLog->event_type = $request->input('eventType', null);
$usageLog->save();
$request->usageLog = $usageLog;
}
return $next($request);
}
private function canAccessRequestedVersion(string $path, array $rules): bool
{
if (strpos($path, 'v1/') === 0) {
return $rules['can_access_legacy_whatnow'];
}
if (strpos($path, 'v2/') === 0) {
return $rules['can_access_preparedness_v2'];
}
return true;
}
private function canAccessOrganisation(string $path, array $rules): bool
{
// Check if accessing org/{code}/whatnow endpoint
if (preg_match('#org/([^/]+)/whatnow#', $path, $matches)) {
$orgCode = $matches[1];
// If allowed_country_code is defined in rules, check if this org is restricted
if (isset($rules['allowed_country_code']) && is_array($rules['allowed_country_code'])) {
if (!in_array($orgCode, $rules['allowed_country_code'])) {
return false;
}
}
}
if (preg_match('#whatnow/(\d+)(?:/|$)#', $path, $matches) && !str_contains($path, 'org/')) {
if (isset($rules['allowed_country_code']) && is_array($rules['allowed_country_code'])) {
$whatnowId = $matches[1];
$entity = WhatNowEntity::with('organisation')->find($whatnowId);
if (!$entity || !$entity->organisation) {
return false;
}
if (!in_array($entity->organisation->country_code, $rules['allowed_country_code'])) {
return false;
}
}
}
return true;
}
}