From 6fa86191b9c07f4be33bc42cb8eb794686b88ad0 Mon Sep 17 00:00:00 2001 From: l-dufour Date: Fri, 12 Sep 2025 11:35:13 -0300 Subject: [PATCH 1/3] add overrides for cipher-base and sha.js in package.json --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 86decfd..2cd3dd2 100644 --- a/package.json +++ b/package.json @@ -18,5 +18,9 @@ "sass": "^1.15.2", "sass-loader": "^7.1.0", "vue-template-compiler": "^2.7.16" + }, + "overrides": { + "cipher-base": "^1.0.5", + "sha.js": "^2.4.12" } } From ed9b7eae9243f86a97a5c82190273a2db236024e Mon Sep 17 00:00:00 2001 From: Juan24 <93536474+juanbroder24@users.noreply.github.com> Date: Mon, 22 Sep 2025 17:07:44 -0300 Subject: [PATCH 2/3] Add is_active flag to applications and related endpoints Introduces an is_active boolean column to the applications table with a migration, updates the Application model with an active scope and proper casting, and refactors ApplicationController to support activation/deactivation, filtering by active status, and improved validation. The API routes are extended to include endpoints for activating, deactivating, and listing all applications for admins. The ApiAuthMiddleware now checks the is_active status for API key authentication and returns appropriate error responses for inactive applications. --- .../Controllers/ApplicationController.php | 438 ++++++++++++------ app/Http/Middleware/ApiAuthMiddleware.php | 45 +- app/Models/Application.php | 25 +- ...459_add_is_active_to_aplications_table.php | 32 ++ routes/api.php | 8 +- 5 files changed, 383 insertions(+), 165 deletions(-) create mode 100644 database/migrations/2025_09_12_162459_add_is_active_to_aplications_table.php diff --git a/app/Http/Controllers/ApplicationController.php b/app/Http/Controllers/ApplicationController.php index 64f4fa9..f7b2071 100644 --- a/app/Http/Controllers/ApplicationController.php +++ b/app/Http/Controllers/ApplicationController.php @@ -2,12 +2,11 @@ namespace App\Http\Controllers; -use App\Classes\Repositories\ApplicationRepositoryInterface; -use App\Classes\Transformers\ApplicationTransformer; -use Illuminate\Database\Eloquent\Collection; +use App\Models\Application; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Log; -use League\Fractal\Manager; +use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Validator; /** * @OA\Tag( @@ -18,47 +17,10 @@ class ApplicationController extends Controller { /** - * @var ApplicationRepositoryInterface - */ - protected $repo; - - /** - * @var Request - */ - protected $request; - - /** - * @var Manager - */ - protected $manager; - - /** - * When more tenants are added, this will be inferred from the auth token that was used. - * - * @var int - */ - private $tenantId = 1; - - /** - * Create a new controller instance. + * Get all active applications for the authenticated user * - * @param ApplicationRepositoryInterface $repo * @param Request $request - * @param Manager $manager - */ - public function __construct( - ApplicationRepositoryInterface $repo, - Request $request, - Manager $manager - ) { - $this->repo = $repo; - $this->request = $request; - $this->manager = $manager; - } - - /** - * @param Request $request - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse */ /** * @OA\Get( @@ -87,35 +49,41 @@ public function __construct( */ public function getAllForUser(Request $request) { - $this->validate($this->request, [ - 'userId' => 'required|string', - ]); + try { + // Obtener el userId del parámetro de query + $userId = $request->query('userId'); - $userId = $request->get('userId', null); - $tenantId = $this->tenantId; + // Validar que se proporcione el userId + if (!$userId) { + return response()->json([ + 'success' => false, + 'message' => 'userId parameter is required' + ], 400); + } - try { - /** @var Collection $apps */ - $apps = $this->repo->findForUserId($tenantId, $userId); - } catch (\Exception $e) { - Log::error('Could not get Applications list for user', ['message' => $e->getMessage()]); + $applications = Application::where('tenant_user_id', $userId) + ->active() + ->get(); + + return response()->json([ + 'success' => true, + 'data' => $applications, + 'message' => 'Applications retrieved successfully' + ], 200); + } catch (\Exception $e) { return response()->json([ - 'status' => 500, - 'error_message' => 'Could not get Applications list', - 'errors' => [], + 'success' => false, + 'message' => 'Error retrieving applications: ' . $e->getMessage() ], 500); } - - $resource = new \League\Fractal\Resource\Collection($apps, new ApplicationTransformer); - $response = $this->manager->createData($resource); - - return response()->json($response->toArray(), 200); } /** + * Get a specific active application by ID + * * @param int $id - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse */ /** * @OA\Get( @@ -142,32 +110,44 @@ public function getAllForUser(Request $request) * ) * ) */ - public function getById($id) + public function getById(Request $request, $id) { try { - $application = $this->repo->find($id); - } catch (\Exception $e) { - Log::error('Application not found', ['message' => $e->getMessage()]); + // Obtener el userId del parámetro de query + $userId = $request->query('userId'); + + // Validar que se proporcione el userId + if (!$userId) { + return response()->json([ + 'success' => false, + 'message' => 'userId parameter is required' + ], 400); + } + + $application = Application::where('id', $id) + ->where('tenant_user_id', $userId) + ->active() + ->first(); + + if (!$application) { + return response()->json([ + 'success' => false, + 'message' => 'Active application not found' + ], 404); + } return response()->json([ - 'status' => 404, - 'error_message' => 'Application does not exist', - 'errors' => ['No matching Application'], - ], 404); - } + 'success' => true, + 'data' => $application, + 'message' => 'Application retrieved successfully' + ], 200); - if ($application->tenant_id !== $this->tenantId) { + } catch (\Exception $e) { return response()->json([ - 'status' => 403, - 'error_message' => 'Application does not belong to tenant', - 'errors' => ['Application does not belong to tenant'], - ], 403); + 'success' => false, + 'message' => 'Error retrieving application: ' . $e->getMessage() + ], 500); } - - $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); - $response = $this->manager->createData($resource); - - return response()->json($response->toArray(), 200); } /** @@ -205,35 +185,59 @@ public function getById($id) */ public function create(Request $request) { - $this->validate($this->request, [ - 'name' => 'required|string', - 'description' => 'string', - 'userId' => 'required|string', - 'estimatedUsers' => 'sometimes|integer', - ]); - + try { + $validator = Validator::make($request->all(), [ + 'name' => 'required|string|max:255', + 'description' => 'nullable|string', + 'estimated_users_count' => 'nullable|integer|min:1', + 'is_active' => 'nullable|boolean', + 'userId' => 'required|string' + ]); + + if ($validator->fails()) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed', + 'errors' => $validator->errors() + ], 422); + } + + // Obtener el userId del request + $userId = $request->input('userId'); + + // Generar la clave API + $apiKey = Application::generateKey(); + + // Verificar que la clave se generó correctamente + if (!$apiKey) { + return response()->json([ + 'success' => false, + 'message' => 'Failed to generate API key' + ], 500); + } + + $application = Application::create([ + 'tenant_id' => 1, + 'tenant_user_id' => $userId, + 'name' => $request->input('name'), + 'description' => $request->input('description'), + 'estimated_users_count' => $request->input('estimated_users_count', $request->input('estimatedUsers', 0)), + 'key' => $apiKey, + 'is_active' => $request->input('is_active', true) + ]); - $data = $this->request->except('userId'); - $data['estimated_users_count'] = $request->get('estimatedUsers', 0); - $data['tenant_user_id'] = $request->get('userId'); - $data['tenant_id'] = $this->tenantId; + return response()->json([ + 'success' => true, + 'data' => $application, + 'message' => 'Application created successfully' + ], 201); - try { - $application = $this->repo->create($data); } catch (\Exception $e) { - Log::error('Application not created', ['message' => $e->getMessage()]); - return response()->json([ - 'status' => 500, - 'error_message' => 'Unable to create Application', - 'errors' => [$e->getMessage()], + 'success' => false, + 'message' => 'Error creating application: ' . $e->getMessage() ], 500); } - - $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); - $response = $this->manager->createData($resource); - - return response()->json($response->toArray(), 201); } /** @@ -269,31 +273,61 @@ public function create(Request $request) */ public function update(Request $request, $id) { - $this->validate($this->request, [ - 'estimatedUsers' => 'sometimes|integer', - ]); + try { + $validator = Validator::make($request->all(), [ + 'name' => 'nullable|string|max:255', + 'description' => 'nullable|string', + 'estimated_users_count' => 'nullable|integer|min:1', + 'is_active' => 'nullable|boolean', + 'userId' => 'required|string' + ]); + + if ($validator->fails()) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed', + 'errors' => $validator->errors() + ], 422); + } + + // Obtener el userId del request + $userId = $request->input('userId'); + + $application = Application::where('id', $id) + ->where('tenant_user_id', $userId) + ->first(); + + if (!$application) { + return response()->json([ + 'success' => false, + 'message' => 'Application not found' + ], 404); + } + + // Actualizar solo los campos proporcionados + $updateData = array_filter($request->only([ + 'name', + 'description', + 'estimated_users_count', + 'is_active' + ]), function($value) { + return $value !== null; + }); + + $application->update($updateData); - $data = []; - $data['estimated_users_count'] = $request->get('estimatedUsers', 0); + return response()->json([ + 'success' => true, + 'data' => $application->fresh(), + 'message' => 'Application updated successfully' + ], 200); - try { - $this->repo->updateWithIdAndInput($id, $data); } catch (\Exception $e) { - Log::error('Application not updated', ['message' => $e->getMessage()]); - return response()->json([ - 'status' => 500, - 'error_message' => 'Unable to update Application', - 'errors' => [$e->getMessage()], + 'success' => false, + 'message' => 'Error updating application: ' . $e->getMessage() ], 500); } - - $application = $this->repo->find($id); - - $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); - $response = $this->manager->createData($resource); - - return response()->json($response->toArray(), 201); } /** @@ -321,43 +355,151 @@ public function update(Request $request, $id) * ) * ) */ - public function delete($id) + public function delete(Request $request, $id) { try { - $application = $this->repo->find($id); - } catch (\Exception $e) { - Log::error('Application not found', ['message' => $e->getMessage()]); + + $userId = $request->query('userId'); + + if (!$userId) { + return response()->json([ + 'success' => false, + 'message' => 'userId parameter is required' + ], 400); + } + + $application = Application::where('id', $id) + ->where('tenant_user_id', $userId) + ->first(); + + if (!$application) { + return response()->json([ + 'success' => false, + 'message' => 'Application not found' + ], 404); + } + + $application->delete(); return response()->json([ - 'status' => 404, - 'error_message' => 'Application does not exist', - 'errors' => ['No matching Application'], - ], 404); - } + 'success' => true, + 'message' => 'Application deleted successfully' + ], 200); - if ($application->tenant_id !== $this->tenantId) { + } catch (\Exception $e) { return response()->json([ - 'status' => 403, - 'error_message' => 'Application does not belong to tenant', - 'errors' => ['Application does not belong to tenant'], - ], 403); + 'success' => false, + 'message' => 'Error deleting application: ' . $e->getMessage() + ], 500); } + } + /** + * Get all applications for admin (including inactive ones) + * This method can be used by administrators to see all applications + * + * @param Request $request + * @return JsonResponse + */ + public function getAllForAdmin(Request $request) + { try { - $this->repo->destroy($id); + $applications = Application::all(); + + return response()->json([ + 'success' => true, + 'data' => $applications, + 'message' => 'All applications retrieved successfully' + ], 200); + } catch (\Exception $e) { - Log::error('Application not found', ['message' => $e->getMessage()]); + return response()->json([ + 'success' => false, + 'message' => 'Error retrieving applications: ' . $e->getMessage() + ], 500); + } + } + + /** + * Activate all applications for a specific user + * + * @param int $id - User ID (tenant_user_id) + * @return JsonResponse + */ + public function activate(Request $request, $id) + { + try { + + $userId = $id; + + $applications = Application::where('tenant_user_id', $userId)->get(); + + if ($applications->isEmpty()) { + return response()->json([ + 'success' => false, + 'message' => 'No applications found for this user' + ], 404); + } + + $updatedCount = Application::where('tenant_user_id', $userId) + ->update(['is_active' => true]); + + return response()->json([ + 'success' => true, + 'data' => [ + 'user_id' => $userId, + 'updated_applications_count' => $updatedCount + ], + 'message' => 'All applications activated successfully for user ' . $userId + ], 200); + + } catch (\Exception $e) { return response()->json([ - 'status' => 404, - 'error_message' => 'Application does not exist', - 'errors' => ['No matching Application'], - ], 404); + 'success' => false, + 'message' => 'Error activating applications: ' . $e->getMessage() + ], 500); } + } - return response()->json([ - 'status' => 200, - 'message' => 'Application deleted', - ], 200); + /** + * Deactivate all applications for a specific user + * + * @param int $id - User ID (tenant_user_id) + * @return JsonResponse + */ + public function deactivate(Request $request, $id) + { + try { + + $userId = $id; + + $applications = Application::where('tenant_user_id', $userId)->get(); + + if ($applications->isEmpty()) { + return response()->json([ + 'success' => false, + 'message' => 'No applications found for this user' + ], 404); + } + + $updatedCount = Application::where('tenant_user_id', $userId) + ->update(['is_active' => false]); + + return response()->json([ + 'success' => true, + 'data' => [ + 'user_id' => $userId, + 'updated_applications_count' => $updatedCount + ], + 'message' => 'All applications deactivated successfully for user ' . $userId + ], 200); + + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => 'Error deactivating applications: ' . $e->getMessage() + ], 500); + } } } diff --git a/app/Http/Middleware/ApiAuthMiddleware.php b/app/Http/Middleware/ApiAuthMiddleware.php index d3f1dc0..01ffeb7 100644 --- a/app/Http/Middleware/ApiAuthMiddleware.php +++ b/app/Http/Middleware/ApiAuthMiddleware.php @@ -6,7 +6,6 @@ use App\Models\UsageLog; use Carbon\Carbon; use Closure; -use Illuminate\Support\Facades\Log; class ApiAuthMiddleware extends BasicAuthMiddleware { @@ -19,22 +18,40 @@ class ApiAuthMiddleware extends BasicAuthMiddleware */ public function handle($request, Closure $next) { - $application = Application::where('key', '=', $request->header('x-api-key'))->first(); + $apiKey = $request->header('x-api-key'); + $authHeader = $request->header('Authorization'); + $isBasicAuth = $authHeader && str_starts_with($authHeader, 'Basic '); - if (! $application) { + if (!$apiKey && !$isBasicAuth) { + return response()->json(['error' => 'Authentication required. Provide API key or Basic auth'], 401); + } + + if ($isBasicAuth) { return parent::handle($request, $next); } - $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; + + if ($apiKey) { + $application = Application::where('key', '=', $apiKey)->first(); + + if (!$application) { + return response()->json(['error' => 'Invalid API key'], 401); + } + + if (!$application->is_active) { + return response()->json(['error' => 'Application is inactive'], 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); } diff --git a/app/Models/Application.php b/app/Models/Application.php index 2c1f6db..1339591 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -16,7 +16,7 @@ class Application extends Model */ protected $table = 'applications'; - public $timestamps = false; + public $timestamps = true; /** * The attributes that are mass assignable. @@ -30,10 +30,31 @@ class Application extends Model 'description', 'estimated_users_count', 'key', + 'is_active', ]; protected $dates = ['deleted_at']; + /** + * The attributes that should be cast to native types. + * + * @var array + */ + protected $casts = [ + 'is_active' => 'boolean', + ]; + + /** + * Scope to get only active applications + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeActive($query) + { + return $query->where('is_active', true); + } + /** * A sure method to generate a unique API key * @@ -42,7 +63,7 @@ class Application extends Model public static function generateKey() { do { - $newKey = str_random(32); + $newKey = \Illuminate\Support\Str::random(32); } // Already in the DB? Fail. Try again while (self::keyExists($newKey)); diff --git a/database/migrations/2025_09_12_162459_add_is_active_to_aplications_table.php b/database/migrations/2025_09_12_162459_add_is_active_to_aplications_table.php new file mode 100644 index 0000000..51f9fd3 --- /dev/null +++ b/database/migrations/2025_09_12_162459_add_is_active_to_aplications_table.php @@ -0,0 +1,32 @@ +boolean('is_active')->default(true)->after('key'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('applications', function (Blueprint $table) { + $table->dropColumn('is_active'); + }); + } +} diff --git a/routes/api.php b/routes/api.php index 6555624..1698e1f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -64,6 +64,11 @@ Route::delete('apps/{id}', 'ApplicationController@delete'); Route::patch('apps/{id}', 'ApplicationController@update'); + // Rutas adicionales para manejar el estado activo/inactivo + Route::patch('apps/{id}/activate', 'ApplicationController@activate'); + Route::patch('apps/{id}/deactivate', 'ApplicationController@deactivate'); + Route::get('admin/apps', 'ApplicationController@getAllForAdmin'); + // Usage log endpoints Route::get('usage/applications', 'UsageLogController@getApplicationLogs'); Route::get('usage/endpoints', 'UsageLogController@getEndpointLogs'); @@ -95,4 +100,5 @@ 'error' => 'API version v1 is no longer supported. Please use /v2/.' ], 410); })->where('any', '.*'); -}); \ No newline at end of file +}); + From fd720ff13478bacf700ba580ab8d39d4fcc01d26 Mon Sep 17 00:00:00 2001 From: Juan24 <93536474+juanbroder24@users.noreply.github.com> Date: Wed, 8 Oct 2025 12:17:04 -0300 Subject: [PATCH 3/3] restore ApplicationController.php --- .../Controllers/ApplicationController.php | 520 +++++++++--------- 1 file changed, 256 insertions(+), 264 deletions(-) diff --git a/app/Http/Controllers/ApplicationController.php b/app/Http/Controllers/ApplicationController.php index f7b2071..53df414 100644 --- a/app/Http/Controllers/ApplicationController.php +++ b/app/Http/Controllers/ApplicationController.php @@ -2,11 +2,12 @@ namespace App\Http\Controllers; -use App\Models\Application; +use App\Classes\Repositories\ApplicationRepositoryInterface; +use App\Classes\Transformers\ApplicationTransformer; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; -use Illuminate\Http\JsonResponse; -use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Facades\Log; +use League\Fractal\Manager; /** * @OA\Tag( @@ -17,10 +18,47 @@ class ApplicationController extends Controller { /** - * Get all active applications for the authenticated user + * @var ApplicationRepositoryInterface + */ + protected $repo; + + /** + * @var Request + */ + protected $request; + + /** + * @var Manager + */ + protected $manager; + + /** + * When more tenants are added, this will be inferred from the auth token that was used. * + * @var int + */ + private $tenantId = 1; + + /** + * Create a new controller instance. + * + * @param ApplicationRepositoryInterface $repo + * @param Request $request + * @param Manager $manager + */ + public function __construct( + ApplicationRepositoryInterface $repo, + Request $request, + Manager $manager + ) { + $this->repo = $repo; + $this->request = $request; + $this->manager = $manager; + } + + /** * @param Request $request - * @return JsonResponse + * @return \Symfony\Component\HttpFoundation\Response */ /** * @OA\Get( @@ -49,41 +87,35 @@ class ApplicationController extends Controller */ public function getAllForUser(Request $request) { - try { - // Obtener el userId del parámetro de query - $userId = $request->query('userId'); + $this->validate($this->request, [ + 'userId' => 'required|string', + ]); - // Validar que se proporcione el userId - if (!$userId) { - return response()->json([ - 'success' => false, - 'message' => 'userId parameter is required' - ], 400); - } - - $applications = Application::where('tenant_user_id', $userId) - ->active() - ->get(); - - return response()->json([ - 'success' => true, - 'data' => $applications, - 'message' => 'Applications retrieved successfully' - ], 200); + $userId = $request->get('userId', null); + $tenantId = $this->tenantId; + try { + /** @var Collection $apps */ + $apps = $this->repo->findForUserId($tenantId, $userId); } catch (\Exception $e) { + Log::error('Could not get Applications list for user', ['message' => $e->getMessage()]); + return response()->json([ - 'success' => false, - 'message' => 'Error retrieving applications: ' . $e->getMessage() + 'status' => 500, + 'error_message' => 'Could not get Applications list', + 'errors' => [], ], 500); } + + $resource = new \League\Fractal\Resource\Collection($apps, new ApplicationTransformer); + $response = $this->manager->createData($resource); + + return response()->json($response->toArray(), 200); } /** - * Get a specific active application by ID - * * @param int $id - * @return JsonResponse + * @return \Symfony\Component\HttpFoundation\Response */ /** * @OA\Get( @@ -110,44 +142,32 @@ public function getAllForUser(Request $request) * ) * ) */ - public function getById(Request $request, $id) + public function getById($id) { try { - // Obtener el userId del parámetro de query - $userId = $request->query('userId'); - - // Validar que se proporcione el userId - if (!$userId) { - return response()->json([ - 'success' => false, - 'message' => 'userId parameter is required' - ], 400); - } - - $application = Application::where('id', $id) - ->where('tenant_user_id', $userId) - ->active() - ->first(); - - if (!$application) { - return response()->json([ - 'success' => false, - 'message' => 'Active application not found' - ], 404); - } + $application = $this->repo->find($id); + } catch (\Exception $e) { + Log::error('Application not found', ['message' => $e->getMessage()]); return response()->json([ - 'success' => true, - 'data' => $application, - 'message' => 'Application retrieved successfully' - ], 200); + 'status' => 404, + 'error_message' => 'Application does not exist', + 'errors' => ['No matching Application'], + ], 404); + } - } catch (\Exception $e) { + if ($application->tenant_id !== $this->tenantId) { return response()->json([ - 'success' => false, - 'message' => 'Error retrieving application: ' . $e->getMessage() - ], 500); + 'status' => 403, + 'error_message' => 'Application does not belong to tenant', + 'errors' => ['Application does not belong to tenant'], + ], 403); } + + $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); + $response = $this->manager->createData($resource); + + return response()->json($response->toArray(), 200); } /** @@ -185,59 +205,35 @@ public function getById(Request $request, $id) */ public function create(Request $request) { - try { - $validator = Validator::make($request->all(), [ - 'name' => 'required|string|max:255', - 'description' => 'nullable|string', - 'estimated_users_count' => 'nullable|integer|min:1', - 'is_active' => 'nullable|boolean', - 'userId' => 'required|string' - ]); - - if ($validator->fails()) { - return response()->json([ - 'success' => false, - 'message' => 'Validation failed', - 'errors' => $validator->errors() - ], 422); - } - - // Obtener el userId del request - $userId = $request->input('userId'); - - // Generar la clave API - $apiKey = Application::generateKey(); - - // Verificar que la clave se generó correctamente - if (!$apiKey) { - return response()->json([ - 'success' => false, - 'message' => 'Failed to generate API key' - ], 500); - } - - $application = Application::create([ - 'tenant_id' => 1, - 'tenant_user_id' => $userId, - 'name' => $request->input('name'), - 'description' => $request->input('description'), - 'estimated_users_count' => $request->input('estimated_users_count', $request->input('estimatedUsers', 0)), - 'key' => $apiKey, - 'is_active' => $request->input('is_active', true) - ]); + $this->validate($this->request, [ + 'name' => 'required|string', + 'description' => 'string', + 'userId' => 'required|string', + 'estimatedUsers' => 'sometimes|integer', + ]); - return response()->json([ - 'success' => true, - 'data' => $application, - 'message' => 'Application created successfully' - ], 201); + $data = $this->request->except('userId'); + $data['estimated_users_count'] = $request->get('estimatedUsers', 0); + $data['tenant_user_id'] = $request->get('userId'); + $data['tenant_id'] = $this->tenantId; + + try { + $application = $this->repo->create($data); } catch (\Exception $e) { + Log::error('Application not created', ['message' => $e->getMessage()]); + return response()->json([ - 'success' => false, - 'message' => 'Error creating application: ' . $e->getMessage() + 'status' => 500, + 'error_message' => 'Unable to create Application', + 'errors' => [$e->getMessage()], ], 500); } + + $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); + $response = $this->manager->createData($resource); + + return response()->json($response->toArray(), 201); } /** @@ -273,61 +269,31 @@ public function create(Request $request) */ public function update(Request $request, $id) { - try { - $validator = Validator::make($request->all(), [ - 'name' => 'nullable|string|max:255', - 'description' => 'nullable|string', - 'estimated_users_count' => 'nullable|integer|min:1', - 'is_active' => 'nullable|boolean', - 'userId' => 'required|string' - ]); - - if ($validator->fails()) { - return response()->json([ - 'success' => false, - 'message' => 'Validation failed', - 'errors' => $validator->errors() - ], 422); - } - - // Obtener el userId del request - $userId = $request->input('userId'); - - $application = Application::where('id', $id) - ->where('tenant_user_id', $userId) - ->first(); - - if (!$application) { - return response()->json([ - 'success' => false, - 'message' => 'Application not found' - ], 404); - } - - // Actualizar solo los campos proporcionados - $updateData = array_filter($request->only([ - 'name', - 'description', - 'estimated_users_count', - 'is_active' - ]), function($value) { - return $value !== null; - }); - - $application->update($updateData); + $this->validate($this->request, [ + 'estimatedUsers' => 'sometimes|integer', + ]); - return response()->json([ - 'success' => true, - 'data' => $application->fresh(), - 'message' => 'Application updated successfully' - ], 200); + $data = []; + $data['estimated_users_count'] = $request->get('estimatedUsers', 0); + try { + $this->repo->updateWithIdAndInput($id, $data); } catch (\Exception $e) { + Log::error('Application not updated', ['message' => $e->getMessage()]); + return response()->json([ - 'success' => false, - 'message' => 'Error updating application: ' . $e->getMessage() + 'status' => 500, + 'error_message' => 'Unable to update Application', + 'errors' => [$e->getMessage()], ], 500); } + + $application = $this->repo->find($id); + + $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); + $response = $this->manager->createData($resource); + + return response()->json($response->toArray(), 201); } /** @@ -355,151 +321,177 @@ public function update(Request $request, $id) * ) * ) */ - public function delete(Request $request, $id) + public function delete($id) { try { - - $userId = $request->query('userId'); - - if (!$userId) { - return response()->json([ - 'success' => false, - 'message' => 'userId parameter is required' - ], 400); - } - - $application = Application::where('id', $id) - ->where('tenant_user_id', $userId) - ->first(); - - if (!$application) { - return response()->json([ - 'success' => false, - 'message' => 'Application not found' - ], 404); - } - - $application->delete(); + $application = $this->repo->find($id); + } catch (\Exception $e) { + Log::error('Application not found', ['message' => $e->getMessage()]); return response()->json([ - 'success' => true, - 'message' => 'Application deleted successfully' - ], 200); + 'status' => 404, + 'error_message' => 'Application does not exist', + 'errors' => ['No matching Application'], + ], 404); + } - } catch (\Exception $e) { + if ($application->tenant_id !== $this->tenantId) { return response()->json([ - 'success' => false, - 'message' => 'Error deleting application: ' . $e->getMessage() - ], 500); + 'status' => 403, + 'error_message' => 'Application does not belong to tenant', + 'errors' => ['Application does not belong to tenant'], + ], 403); } - } - /** - * Get all applications for admin (including inactive ones) - * This method can be used by administrators to see all applications - * - * @param Request $request - * @return JsonResponse - */ - public function getAllForAdmin(Request $request) - { try { - $applications = Application::all(); - - return response()->json([ - 'success' => true, - 'data' => $applications, - 'message' => 'All applications retrieved successfully' - ], 200); - + $this->repo->destroy($id); } catch (\Exception $e) { + Log::error('Application not found', ['message' => $e->getMessage()]); + return response()->json([ - 'success' => false, - 'message' => 'Error retrieving applications: ' . $e->getMessage() - ], 500); + 'status' => 404, + 'error_message' => 'Application does not exist', + 'errors' => ['No matching Application'], + ], 404); } + + return response()->json([ + 'status' => 200, + 'message' => 'Application deleted', + ], 200); } /** - * Activate all applications for a specific user - * - * @param int $id - User ID (tenant_user_id) - * @return JsonResponse + * @OA\Patch( + * path="/apps/{id}/activate", + * tags={"Applications"}, + * summary="Activate an application by ID", + * operationId="activateApplication", + * security={}, + * deprecated=true, + * @OA\Parameter( + * name="id", + * in="path", + * required=true, + * description="ID of the application to activate", + * @OA\Schema(type="integer", format="int64") + * ), + * @OA\Response( + * response=200, + * description="Successful response", + * @OA\JsonContent( + * type="object", + * @OA\Property(property="data", type="array", @OA\Items(type="object")) + * ) + * ) + * ) */ - public function activate(Request $request, $id) + public function activate($id) { try { + $application = $this->repo->find($id); + } catch (\Exception $e) { + Log::error('Application not found', ['message' => $e->getMessage()]); - $userId = $id; - - - $applications = Application::where('tenant_user_id', $userId)->get(); - - if ($applications->isEmpty()) { - return response()->json([ - 'success' => false, - 'message' => 'No applications found for this user' - ], 404); - } - - $updatedCount = Application::where('tenant_user_id', $userId) - ->update(['is_active' => true]); + return response()->json([ + 'status' => 404, + 'error_message' => 'Application does not exist', + 'errors' => ['No matching Application'], + ], 404); + } + if ($application->tenant_id !== $this->tenantId) { return response()->json([ - 'success' => true, - 'data' => [ - 'user_id' => $userId, - 'updated_applications_count' => $updatedCount - ], - 'message' => 'All applications activated successfully for user ' . $userId - ], 200); + 'status' => 403, + 'error_message' => 'Application does not belong to tenant', + 'errors' => ['Application does not belong to tenant'], + ], 403); + } + try { + $this->repo->updateWithIdAndInput($id, ['is_active' => true]); } catch (\Exception $e) { + Log::error('Application not activated', ['message' => $e->getMessage()]); + return response()->json([ - 'success' => false, - 'message' => 'Error activating applications: ' . $e->getMessage() + 'status' => 500, + 'error_message' => 'Unable to activate Application', + 'errors' => [$e->getMessage()], ], 500); } + + $application = $this->repo->find($id); + + $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); + $response = $this->manager->createData($resource); + + return response()->json($response->toArray(), 200); } /** - * Deactivate all applications for a specific user - * - * @param int $id - User ID (tenant_user_id) - * @return JsonResponse + * @OA\Patch( + * path="/apps/{id}/deactivate", + * tags={"Applications"}, + * summary="Deactivate an application by ID", + * operationId="deactivateApplication", + * security={}, + * deprecated=true, + * @OA\Parameter( + * name="id", + * in="path", + * required=true, + * description="ID of the application to deactivate", + * @OA\Schema(type="integer", format="int64") + * ), + * @OA\Response( + * response=200, + * description="Successful response", + * @OA\JsonContent( + * type="object", + * @OA\Property(property="data", type="array", @OA\Items(type="object")) + * ) + * ) + * ) */ - public function deactivate(Request $request, $id) + public function deactivate($id) { try { + $application = $this->repo->find($id); + } catch (\Exception $e) { + Log::error('Application not found', ['message' => $e->getMessage()]); - $userId = $id; - - $applications = Application::where('tenant_user_id', $userId)->get(); - - if ($applications->isEmpty()) { - return response()->json([ - 'success' => false, - 'message' => 'No applications found for this user' - ], 404); - } - - $updatedCount = Application::where('tenant_user_id', $userId) - ->update(['is_active' => false]); + return response()->json([ + 'status' => 404, + 'error_message' => 'Application does not exist', + 'errors' => ['No matching Application'], + ], 404); + } + if ($application->tenant_id !== $this->tenantId) { return response()->json([ - 'success' => true, - 'data' => [ - 'user_id' => $userId, - 'updated_applications_count' => $updatedCount - ], - 'message' => 'All applications deactivated successfully for user ' . $userId - ], 200); + 'status' => 403, + 'error_message' => 'Application does not belong to tenant', + 'errors' => ['Application does not belong to tenant'], + ], 403); + } + try { + $this->repo->updateWithIdAndInput($id, ['is_active' => false]); } catch (\Exception $e) { + Log::error('Application not deactivated', ['message' => $e->getMessage()]); + return response()->json([ - 'success' => false, - 'message' => 'Error deactivating applications: ' . $e->getMessage() + 'status' => 500, + 'error_message' => 'Unable to deactivate Application', + 'errors' => [$e->getMessage()], ], 500); } + + $application = $this->repo->find($id); + + $resource = new \League\Fractal\Resource\Item($application, new ApplicationTransformer()); + $response = $this->manager->createData($resource); + + return response()->json($response->toArray(), 200); } }