From 4b84a3d23808966e17f2f0e8247c9c2450b560f7 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Wed, 8 Oct 2025 18:31:28 -0300 Subject: [PATCH 1/4] feat: Add OpenAPI documentation to "getAllUserStories" method - Add controller's response to OpenAPI schema --- .../Main/OAuth2UserStoriesApiController.php | 71 ++++++++++++++++++- app/Swagger/schemas.php | 47 ++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php index a788b903b..8dd92d68b 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php @@ -13,9 +13,11 @@ **/ use App\Models\Foundation\Main\Repositories\IUserStoryRepository; +use Illuminate\Http\Response; use models\oauth2\IResourceServerContext; use models\utils\IEntity; use ModelSerializers\SerializerRegistry; +use OpenApi\Attributes as OA; /** * Class OAuth2UserStoriesApiController @@ -41,6 +43,73 @@ public function __construct $this->repository = $repository; } + // OpenAPI Documentation + + #[OA\Get( + path: '/api/public/v1/user-stories', + summary: 'Get all user stories', + description: 'Retrieves a paginated list of user stories showcasing real-world use cases and success stories from the OpenStack community. User stories highlight how organizations use OpenStack in production. This is a public endpoint that can return different data based on authentication (more details for authenticated users).', + tags: ['User Stories'], + parameters: [ + new OA\Parameter( + name: 'page', + in: 'query', + required: false, + description: 'Page number for pagination', + schema: new OA\Schema(type: 'integer', example: 1) + ), + new OA\Parameter( + name: 'per_page', + in: 'query', + required: false, + description: 'Items per page', + schema: new OA\Schema(type: 'integer', example: 10, maximum: 100) + ), + new OA\Parameter( + name: 'filter[]', + in: 'query', + required: false, + description: 'Filter expressions. Format: fieldvalue. Available field: name (=@, ==, @@). Operators: == (equals), =@ (starts with), @@ (contains)', + style: 'form', + explode: true, + schema: new OA\Schema( + type: 'array', + items: new OA\Items(type: 'string', example: 'name@@cloud') + ) + ), + new OA\Parameter( + name: 'order', + in: 'query', + required: false, + description: 'Order by field(s). Available fields: name, id. Use "-" prefix for descending order.', + schema: new OA\Schema(type: 'string', example: 'name') + ), + new OA\Parameter( + name: 'expand', + in: 'query', + required: false, + description: 'Expand relationships. Available: organization, industry, location, image, tags', + schema: new OA\Schema(type: 'string', example: 'organization,tags') + ), + new OA\Parameter( + name: 'relations', + in: 'query', + required: false, + description: 'Relations to load. Available: tags', + schema: new OA\Schema(type: 'string', example: 'tags') + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'User stories retrieved successfully', + content: new OA\JsonContent(ref: '#/components/schemas/PaginatedUserStoriesResponse') + ), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + /** * @return mixed */ @@ -78,4 +147,4 @@ protected function getEntitySerializerType(): string return !is_null($currentUser) ? SerializerRegistry::SerializerType_Private : SerializerRegistry::SerializerType_Public; } -} \ No newline at end of file +} diff --git a/app/Swagger/schemas.php b/app/Swagger/schemas.php index 02393beb8..7a7317f56 100644 --- a/app/Swagger/schemas.php +++ b/app/Swagger/schemas.php @@ -417,3 +417,50 @@ class ChunkedFileUploadCompleteResponseSchema {} )] class ChunkedFileUploadRequestSchema {} +// User Stories + +#[OA\Schema( + schema: 'UserStory', + type: 'object', + properties: [ + new OA\Property(property: 'id', type: 'integer', example: 1), + new OA\Property(property: 'created', type: 'integer', example: 1633024800, description: 'Unix timestamp when created'), + new OA\Property(property: 'last_edited', type: 'integer', example: 1633111200, description: 'Unix timestamp when last updated'), + new OA\Property(property: 'name', type: 'string', example: 'Large Scale Cloud Infrastructure'), + new OA\Property(property: 'description', type: 'string', example: 'Full description of how this organization uses OpenStack...'), + new OA\Property(property: 'short_description', type: 'string', example: 'Brief overview of the use case'), + new OA\Property(property: 'link', type: 'string', nullable: true, example: 'https://example.com/case-study'), + new OA\Property(property: 'active', type: 'boolean', example: true), + new OA\Property(property: 'is_million_core_club', type: 'boolean', example: false, description: 'Whether this is a million core club member'), + new OA\Property(property: 'organization', type: 'Organization'), + new OA\Property(property: 'industry', type: 'Industry'), + new OA\Property(property: 'location', type: 'Location'), + new OA\Property(property: 'image', type: 'Image'), + new OA\Property( + property: 'tags', + type: 'array', + description: 'Array of tag IDs (use expand=tags for full details)', + items: new OA\Items(type: 'integer'), + example: [1, 2, 3] + ), + ] +)] +class UserStorySchema {} + +#[OA\Schema( + schema: 'PaginatedUserStoriesResponse', + allOf: [ + new OA\Schema(ref: '#/components/schemas/PaginateDataSchemaResponse'), + new OA\Schema( + type: 'object', + properties: [ + new OA\Property( + property: 'data', + type: 'array', + items: new OA\Items(ref: '#/components/schemas/UserStory') + ) + ] + ) + ] +)] +class PaginatedUserStoriesResponseSchema {} From 7651ec18d6e6fe7d2434bd07ab0c0fae6ad1e8fb Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Tue, 14 Oct 2025 14:43:06 -0300 Subject: [PATCH 2/4] fix: Change "namespace" word positioning --- .../Apis/Protected/Main/OAuth2UserStoriesApiController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php index 8dd92d68b..fb15ff803 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php @@ -1,4 +1,7 @@ - Date: Thu, 27 Nov 2025 20:45:07 +0000 Subject: [PATCH 3/4] feat: Add OpenAPI schemas for UserStory, Organization, Continent, File, and UserStoriesIndustry models --- app/Swagger/Models/ContinentSchema.php | 21 ++++++++++ app/Swagger/Models/FileSchema.php | 22 +++++++++++ app/Swagger/Models/OrganizationSchema.php | 21 ++++++++++ .../Models/UserStoriesIndustrySchema.php | 22 +++++++++++ app/Swagger/Models/UserStorySchema.php | 39 +++++++++++++++++++ app/Swagger/schemas.php | 27 ------------- 6 files changed, 125 insertions(+), 27 deletions(-) create mode 100644 app/Swagger/Models/ContinentSchema.php create mode 100644 app/Swagger/Models/FileSchema.php create mode 100644 app/Swagger/Models/OrganizationSchema.php create mode 100644 app/Swagger/Models/UserStoriesIndustrySchema.php create mode 100644 app/Swagger/Models/UserStorySchema.php diff --git a/app/Swagger/Models/ContinentSchema.php b/app/Swagger/Models/ContinentSchema.php new file mode 100644 index 000000000..410d69fef --- /dev/null +++ b/app/Swagger/Models/ContinentSchema.php @@ -0,0 +1,21 @@ + Date: Wed, 3 Dec 2025 20:04:31 +0000 Subject: [PATCH 4/4] feat: Add changes requested --- .../Apis/Protected/Main/OAuth2UserStoriesApiController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php index fb15ff803..b84538a7c 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2UserStoriesApiController.php @@ -50,9 +50,10 @@ public function __construct #[OA\Get( path: '/api/public/v1/user-stories', + operationId: 'getAllUserStories', summary: 'Get all user stories', description: 'Retrieves a paginated list of user stories showcasing real-world use cases and success stories from the OpenStack community. User stories highlight how organizations use OpenStack in production. This is a public endpoint that can return different data based on authentication (more details for authenticated users).', - tags: ['User Stories'], + tags: ['User Stories (Public)'], parameters: [ new OA\Parameter( name: 'page',