From 16a5eb6be34b93e38cb396d6197a68487ef180a5 Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Thu, 19 Feb 2026 21:01:04 +0000 Subject: [PATCH 1/2] feat: Add OpenAPI documentation annotations for OAuth2GroupApiController v1 routes --- .../Api/OAuth2/OAuth2GroupApiController.php | 55 ++++++++++++++++++- app/Swagger/Models/GroupSchema.php | 24 ++++++++ .../OAuth2GroupApiControllerSchemas.php | 26 +++++++++ ...OAuth2GroupApiControllerSecuritySchema.php | 26 +++++++++ 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 app/Swagger/Models/GroupSchema.php create mode 100644 app/Swagger/OAuth2GroupApiControllerSchemas.php create mode 100644 app/Swagger/Security/OAuth2GroupApiControllerSecuritySchema.php diff --git a/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php b/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php index e3288265..1afc6b0d 100644 --- a/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php +++ b/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php @@ -14,20 +14,73 @@ use App\Http\Controllers\GetAllTrait; use App\libs\Auth\Repositories\IGroupRepository; +use App\libs\OAuth2\IGroupScopes; use App\ModelSerializers\SerializerRegistry; use OAuth2\IResourceServerContext; +use OpenApi\Attributes as OA; +use Symfony\Component\HttpFoundation\Response; use Utils\Services\ILogService; /** * Class OAuth2GroupApiController * @package App\Http\Controllers\Api\OAuth2 */ +#[OA\Get( + path: '/api/v1/groups', + operationId: 'getGroups', + summary: 'Get all groups', + description: 'Retrieves a paginated list of groups with optional filtering and ordering.', + security: [['OAuth2GroupsSecurity' => [IGroupScopes::ReadAll]]], + tags: ['Groups'], + parameters: [ + new OA\Parameter( + name: 'page', + in: 'query', + description: 'Page number for pagination', + required: false, + schema: new OA\Schema(type: 'integer', minimum: 1, default: 1, example: 1) + ), + new OA\Parameter( + name: 'per_page', + in: 'query', + description: 'Number of items per page', + required: false, + schema: new OA\Schema(type: 'integer', minimum: 5, maximum: 100, default: 5, example: 10) + ), + new OA\Parameter( + name: 'filter', + in: 'query', + description: 'Filter criteria. Supported filters: slug== (exact match). Example: filter=slug==administrators', + required: false, + schema: new OA\Schema(type: 'string', example: 'slug==administrators') + ), + new OA\Parameter( + name: 'order', + in: 'query', + description: 'Ordering criteria. Supported fields: id, name, slug. Use + for ascending, - for descending. Example: +name or -id', + required: false, + schema: new OA\Schema(type: 'string', example: '+name') + ) + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: 'Successful response with paginated groups', + content: new OA\JsonContent(ref: '#/components/schemas/PaginatedGroupResponse') + ), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: 'Unauthorized'), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: 'Forbidden - insufficient scope'), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: 'Not Found'), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: 'Validation failed, invalid filter or order parameter'), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: 'Server error') + ] +)] final class OAuth2GroupApiController extends OAuth2ProtectedController { use GetAllTrait; /** - * OAuth2UserApiController constructor. + * OAuth2GroupApiController constructor. * @param IGroupRepository $repository * @param IResourceServerContext $resource_server_context * @param ILogService $log_service diff --git a/app/Swagger/Models/GroupSchema.php b/app/Swagger/Models/GroupSchema.php new file mode 100644 index 00000000..af2cef99 --- /dev/null +++ b/app/Swagger/Models/GroupSchema.php @@ -0,0 +1,24 @@ + 'Read all groups', + IGroupScopes::Write => 'Write group', + ] + ), + ] +)] +class OAuth2GroupApiControllerSecuritySchema +{ +} From 5c100aa3320d35a04eea2235c49d13668a31891c Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Mon, 23 Feb 2026 19:47:39 +0000 Subject: [PATCH 2/2] chore: Add PR requested changes bullets 1 and 3 --- .../Api/OAuth2/OAuth2GroupApiController.php | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php b/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php index 1afc6b0d..b8c68093 100644 --- a/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php +++ b/app/Http/Controllers/Api/OAuth2/OAuth2GroupApiController.php @@ -1,4 +1,5 @@ - [IGroupScopes::ReadAll]]], - tags: ['Groups'], - parameters: [ - new OA\Parameter( - name: 'page', - in: 'query', - description: 'Page number for pagination', - required: false, - schema: new OA\Schema(type: 'integer', minimum: 1, default: 1, example: 1) - ), - new OA\Parameter( - name: 'per_page', - in: 'query', - description: 'Number of items per page', - required: false, - schema: new OA\Schema(type: 'integer', minimum: 5, maximum: 100, default: 5, example: 10) - ), - new OA\Parameter( - name: 'filter', - in: 'query', - description: 'Filter criteria. Supported filters: slug== (exact match). Example: filter=slug==administrators', - required: false, - schema: new OA\Schema(type: 'string', example: 'slug==administrators') - ), - new OA\Parameter( - name: 'order', - in: 'query', - description: 'Ordering criteria. Supported fields: id, name, slug. Use + for ascending, - for descending. Example: +name or -id', - required: false, - schema: new OA\Schema(type: 'string', example: '+name') - ) - ], - responses: [ - new OA\Response( - response: Response::HTTP_OK, - description: 'Successful response with paginated groups', - content: new OA\JsonContent(ref: '#/components/schemas/PaginatedGroupResponse') - ), - new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: 'Unauthorized'), - new OA\Response(response: Response::HTTP_FORBIDDEN, description: 'Forbidden - insufficient scope'), - new OA\Response(response: Response::HTTP_NOT_FOUND, description: 'Not Found'), - new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: 'Validation failed, invalid filter or order parameter'), - new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: 'Server error') - ] -)] final class OAuth2GroupApiController extends OAuth2ProtectedController { use GetAllTrait; @@ -90,12 +41,61 @@ public function __construct IGroupRepository $repository, IResourceServerContext $resource_server_context, ILogService $log_service, - ) - { + ) { parent::__construct($resource_server_context, $log_service); $this->repository = $repository; } + #[OA\Get( + path: '/api/v1/groups', + operationId: 'getGroups', + summary: 'Get all groups', + description: 'Retrieves a paginated list of groups with optional filtering and ordering. No route-level middleware enforcement; requires valid OAuth2 bearer token only.', + security: [['OAuth2GroupsSecurity' => [IGroupScopes::ReadAll]]], + tags: ['Groups'], + parameters: [ + new OA\Parameter( + name: 'page', + in: 'query', + description: 'Page number for pagination', + required: false, + schema: new OA\Schema(type: 'integer', minimum: 1, default: 1, example: 1) + ), + new OA\Parameter( + name: 'per_page', + in: 'query', + description: 'Number of items per page', + required: false, + schema: new OA\Schema(type: 'integer', minimum: 5, maximum: 100, default: 5, example: 10) + ), + new OA\Parameter( + name: 'filter', + in: 'query', + description: 'Filter criteria. Supported filters: slug== (exact match). Example: filter=slug==administrators', + required: false, + schema: new OA\Schema(type: 'string', example: 'slug==administrators') + ), + new OA\Parameter( + name: 'order', + in: 'query', + description: 'Ordering criteria. Supported fields: id, name, slug. Use + for ascending, - for descending. Example: +name or -id', + required: false, + schema: new OA\Schema(type: 'string', example: '+name') + ) + ], + responses: [ + new OA\Response( + response: Response::HTTP_OK, + description: 'Successful response with paginated groups', + content: new OA\JsonContent(ref: '#/components/schemas/PaginatedGroupResponse') + ), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: 'Unauthorized'), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: 'Forbidden - insufficient scope'), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: 'Not Found'), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: 'Validation failed, invalid filter or order parameter'), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: 'Server error') + ] + )] protected function getAllSerializerType(): string { return SerializerRegistry::SerializerType_Public;