Skip to content

Commit 76da128

Browse files
Merge pull request #53 from IFRCGo/develop
Develop
2 parents e58a07e + fd720ff commit 76da128

File tree

6 files changed

+231
-17
lines changed

6 files changed

+231
-17
lines changed

app/Http/Controllers/ApplicationController.php

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,4 +360,138 @@ public function delete($id)
360360
'message' => 'Application deleted',
361361
], 200);
362362
}
363+
364+
/**
365+
* @OA\Patch(
366+
* path="/apps/{id}/activate",
367+
* tags={"Applications"},
368+
* summary="Activate an application by ID",
369+
* operationId="activateApplication",
370+
* security={},
371+
* deprecated=true,
372+
* @OA\Parameter(
373+
* name="id",
374+
* in="path",
375+
* required=true,
376+
* description="ID of the application to activate",
377+
* @OA\Schema(type="integer", format="int64")
378+
* ),
379+
* @OA\Response(
380+
* response=200,
381+
* description="Successful response",
382+
* @OA\JsonContent(
383+
* type="object",
384+
* @OA\Property(property="data", type="array", @OA\Items(type="object"))
385+
* )
386+
* )
387+
* )
388+
*/
389+
public function activate($id)
390+
{
391+
try {
392+
$application = $this->repo->find($id);
393+
} catch (\Exception $e) {
394+
Log::error('Application not found', ['message' => $e->getMessage()]);
395+
396+
return response()->json([
397+
'status' => 404,
398+
'error_message' => 'Application does not exist',
399+
'errors' => ['No matching Application'],
400+
], 404);
401+
}
402+
403+
if ($application->tenant_id !== $this->tenantId) {
404+
return response()->json([
405+
'status' => 403,
406+
'error_message' => 'Application does not belong to tenant',
407+
'errors' => ['Application does not belong to tenant'],
408+
], 403);
409+
}
410+
411+
try {
412+
$this->repo->updateWithIdAndInput($id, ['is_active' => true]);
413+
} catch (\Exception $e) {
414+
Log::error('Application not activated', ['message' => $e->getMessage()]);
415+
416+
return response()->json([
417+
'status' => 500,
418+
'error_message' => 'Unable to activate Application',
419+
'errors' => [$e->getMessage()],
420+
], 500);
421+
}
422+
423+
$application = $this->repo->find($id);
424+
425+
$resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer());
426+
$response = $this->manager->createData($resource);
427+
428+
return response()->json($response->toArray(), 200);
429+
}
430+
431+
/**
432+
* @OA\Patch(
433+
* path="/apps/{id}/deactivate",
434+
* tags={"Applications"},
435+
* summary="Deactivate an application by ID",
436+
* operationId="deactivateApplication",
437+
* security={},
438+
* deprecated=true,
439+
* @OA\Parameter(
440+
* name="id",
441+
* in="path",
442+
* required=true,
443+
* description="ID of the application to deactivate",
444+
* @OA\Schema(type="integer", format="int64")
445+
* ),
446+
* @OA\Response(
447+
* response=200,
448+
* description="Successful response",
449+
* @OA\JsonContent(
450+
* type="object",
451+
* @OA\Property(property="data", type="array", @OA\Items(type="object"))
452+
* )
453+
* )
454+
* )
455+
*/
456+
public function deactivate($id)
457+
{
458+
try {
459+
$application = $this->repo->find($id);
460+
} catch (\Exception $e) {
461+
Log::error('Application not found', ['message' => $e->getMessage()]);
462+
463+
return response()->json([
464+
'status' => 404,
465+
'error_message' => 'Application does not exist',
466+
'errors' => ['No matching Application'],
467+
], 404);
468+
}
469+
470+
if ($application->tenant_id !== $this->tenantId) {
471+
return response()->json([
472+
'status' => 403,
473+
'error_message' => 'Application does not belong to tenant',
474+
'errors' => ['Application does not belong to tenant'],
475+
], 403);
476+
}
477+
478+
try {
479+
$this->repo->updateWithIdAndInput($id, ['is_active' => false]);
480+
} catch (\Exception $e) {
481+
Log::error('Application not deactivated', ['message' => $e->getMessage()]);
482+
483+
return response()->json([
484+
'status' => 500,
485+
'error_message' => 'Unable to deactivate Application',
486+
'errors' => [$e->getMessage()],
487+
], 500);
488+
}
489+
490+
$application = $this->repo->find($id);
491+
492+
$resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer());
493+
$response = $this->manager->createData($resource);
494+
495+
return response()->json($response->toArray(), 200);
496+
}
363497
}

app/Http/Middleware/ApiAuthMiddleware.php

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use App\Models\UsageLog;
77
use Carbon\Carbon;
88
use Closure;
9-
use Illuminate\Support\Facades\Log;
109

1110
class ApiAuthMiddleware extends BasicAuthMiddleware
1211
{
@@ -19,22 +18,40 @@ class ApiAuthMiddleware extends BasicAuthMiddleware
1918
*/
2019
public function handle($request, Closure $next)
2120
{
22-
$application = Application::where('key', '=', $request->header('x-api-key'))->first();
21+
$apiKey = $request->header('x-api-key');
22+
$authHeader = $request->header('Authorization');
23+
$isBasicAuth = $authHeader && str_starts_with($authHeader, 'Basic ');
2324

24-
if (! $application) {
25+
if (!$apiKey && !$isBasicAuth) {
26+
return response()->json(['error' => 'Authentication required. Provide API key or Basic auth'], 401);
27+
}
28+
29+
if ($isBasicAuth) {
2530
return parent::handle($request, $next);
2631
}
27-
$usageLog = new UsageLog;
28-
$usageLog->application_id = $application->id;
29-
$usageLog->method = $request->method();
30-
$usageLog->endpoint = $request->path();
31-
$usageLog->timestamp = Carbon::now()->toDateTimeString();
32-
$usageLog->code_status = 200;
33-
$usageLog->language = $request->input('language', false) ? $request->input('language', null) : $request->header('Accept-Language', null);
34-
$usageLog->subnational = $request->input('subnational', null);
35-
$usageLog->event_type = $request->input('eventType', null);
36-
$usageLog->save();
37-
$request->usageLog=$usageLog;
32+
33+
if ($apiKey) {
34+
$application = Application::where('key', '=', $apiKey)->first();
35+
36+
if (!$application) {
37+
return response()->json(['error' => 'Invalid API key'], 401);
38+
}
39+
40+
if (!$application->is_active) {
41+
return response()->json(['error' => 'Application is inactive'], 403);
42+
}
43+
$usageLog = new UsageLog;
44+
$usageLog->application_id = $application->id;
45+
$usageLog->method = $request->method();
46+
$usageLog->endpoint = $request->path();
47+
$usageLog->timestamp = Carbon::now()->toDateTimeString();
48+
$usageLog->code_status = 200;
49+
$usageLog->language = $request->input('language', false) ? $request->input('language', null) : $request->header('Accept-Language', null);
50+
$usageLog->subnational = $request->input('subnational', null);
51+
$usageLog->event_type = $request->input('eventType', null);
52+
$usageLog->save();
53+
$request->usageLog = $usageLog;
54+
}
3855

3956
return $next($request);
4057
}

app/Models/Application.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Application extends Model
1616
*/
1717
protected $table = 'applications';
1818

19-
public $timestamps = false;
19+
public $timestamps = true;
2020

2121
/**
2222
* The attributes that are mass assignable.
@@ -30,10 +30,31 @@ class Application extends Model
3030
'description',
3131
'estimated_users_count',
3232
'key',
33+
'is_active',
3334
];
3435

3536
protected $dates = ['deleted_at'];
3637

38+
/**
39+
* The attributes that should be cast to native types.
40+
*
41+
* @var array
42+
*/
43+
protected $casts = [
44+
'is_active' => 'boolean',
45+
];
46+
47+
/**
48+
* Scope to get only active applications
49+
*
50+
* @param \Illuminate\Database\Eloquent\Builder $query
51+
* @return \Illuminate\Database\Eloquent\Builder
52+
*/
53+
public function scopeActive($query)
54+
{
55+
return $query->where('is_active', true);
56+
}
57+
3758
/**
3859
* A sure method to generate a unique API key
3960
*
@@ -42,7 +63,7 @@ class Application extends Model
4263
public static function generateKey()
4364
{
4465
do {
45-
$newKey = str_random(32);
66+
$newKey = \Illuminate\Support\Str::random(32);
4667
} // Already in the DB? Fail. Try again
4768
while (self::keyExists($newKey));
4869

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class AddIsActiveToAplicationsTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::table('applications', function (Blueprint $table) {
17+
$table->boolean('is_active')->default(true)->after('key');
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*
24+
* @return void
25+
*/
26+
public function down()
27+
{
28+
Schema::table('applications', function (Blueprint $table) {
29+
$table->dropColumn('is_active');
30+
});
31+
}
32+
}

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,9 @@
1818
"sass": "^1.15.2",
1919
"sass-loader": "^7.1.0",
2020
"vue-template-compiler": "^2.7.16"
21+
},
22+
"overrides": {
23+
"cipher-base": "^1.0.5",
24+
"sha.js": "^2.4.12"
2125
}
2226
}

routes/api.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@
6464
Route::delete('apps/{id}', 'ApplicationController@delete');
6565
Route::patch('apps/{id}', 'ApplicationController@update');
6666

67+
// Rutas adicionales para manejar el estado activo/inactivo
68+
Route::patch('apps/{id}/activate', 'ApplicationController@activate');
69+
Route::patch('apps/{id}/deactivate', 'ApplicationController@deactivate');
70+
Route::get('admin/apps', 'ApplicationController@getAllForAdmin');
71+
6772
// Usage log endpoints
6873
Route::get('usage/applications', 'UsageLogController@getApplicationLogs');
6974
Route::get('usage/endpoints', 'UsageLogController@getEndpointLogs');
@@ -95,4 +100,5 @@
95100
'error' => 'API version v1 is no longer supported. Please use /v2/.'
96101
], 410);
97102
})->where('any', '.*');
98-
});
103+
});
104+

0 commit comments

Comments
 (0)