Skip to content

Commit 1727cb9

Browse files
matiasperrone-exosmarcetmatiasperrone
authored
Feature | Extend Swagger Coverage for controller OAuth2SummitBadgesApiController (#380)
* chore: add to table SummitAttendeeTicket fild summit id to improve performance chore: add needed IDX * feat: Extend Swagger Coverage for controller Apis/Protected/Summit/OAuth2SummitBadgesApiController.php * chore: Move schemas to the new app/Swagger/SummitSchemas.php file * fix: error HTTP responses and remove reference * fix: Remove unnecessary schemas and double require * fix: incorrect types and descriptions for errors * fix: Change "namespace" word positioning * fix: add the right security schema * fix: minort text Title case * chore: Move the security schema for the controller to its own file * chore: add operationId * chore: remove expand fields and add a description in related fields to be expanded * fix: owner email example * fix: title case on description for Not Found * chore: include PR requested changes * chore: move SummitBadgeFeatureType schema to its own file (rebase to main issue) * chore: move to OpenAPI 3.1 --------- Co-authored-by: smarcet <smarcet@gmail.com> Co-authored-by: Matias Perrone <github@matiasperrone.com>
1 parent 84831d2 commit 1727cb9

6 files changed

Lines changed: 328 additions & 67 deletions

File tree

Lines changed: 184 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
<?php namespace App\Http\Controllers;
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
25
/**
36
* Copyright 2019 OpenStack Foundation
47
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,9 +15,12 @@
1215
* limitations under the License.
1316
**/
1417
use App\Models\Foundation\Summit\Repositories\ISummitAttendeeBadgeRepository;
18+
use App\Security\SummitScopes;
1519
use models\oauth2\IResourceServerContext;
1620
use models\summit\ISummitRepository;
1721
use ModelSerializers\SerializerRegistry;
22+
use OpenApi\Attributes as OA;
23+
use Symfony\Component\HttpFoundation\Response;
1824
use utils\Filter;
1925
use utils\FilterElement;
2026

@@ -37,8 +43,7 @@ public function __construct
3743
ISummitAttendeeBadgeRepository $repository,
3844
ISummitRepository $summit_repository,
3945
IResourceServerContext $resource_server_context
40-
)
41-
{
46+
) {
4247
parent::__construct($resource_server_context);
4348
$this->repository = $repository;
4449
$this->summit_repository = $summit_repository;
@@ -52,109 +57,240 @@ protected function getSummitRepository(): ISummitRepository
5257
return $this->summit_repository;
5358
}
5459

60+
// OpenAPI Documentation
61+
62+
#[OA\Get(
63+
path: '/api/v1/summits/{id}/badges',
64+
operationId: 'getAllBySummit',
65+
summary: 'Get all attendee badges for a summit',
66+
description: 'Retrieves a paginated list of attendee badges for a specific summit. Badges are issued to attendees and contain ticket information, badge type, printing details, and feature assignments (ribbons, special access indicators, etc.).',
67+
security: [['summit_badges_api_oauth2' => [SummitScopes::ReadAllSummitData]]],
68+
tags: ['Summit Badges'],
69+
parameters: [
70+
new OA\Parameter(
71+
name: 'id',
72+
in: 'path',
73+
required: true,
74+
description: 'Summit ID',
75+
schema: new OA\Schema(type: 'integer')
76+
),
77+
new OA\Parameter(
78+
name: 'page',
79+
in: 'query',
80+
required: false,
81+
description: 'Page number for pagination',
82+
schema: new OA\Schema(type: 'integer', example: 1)
83+
),
84+
new OA\Parameter(
85+
name: 'per_page',
86+
in: 'query',
87+
required: false,
88+
description: 'Items per page',
89+
schema: new OA\Schema(type: 'integer', example: 10, maximum: 100)
90+
),
91+
new OA\Parameter(
92+
name: 'filter[]',
93+
in: 'query',
94+
required: false,
95+
description: 'Filter expressions. Format: field<op>value. Available fields: owner_first_name, owner_last_name, owner_full_name, owner_email, ticket_number, order_number (all support =@, ==). Operators: == (equals), =@ (contains)',
96+
style: 'form',
97+
explode: true,
98+
schema: new OA\Schema(
99+
type: 'array',
100+
items: new OA\Items(type: 'string', example: 'owner_email==john@example.com')
101+
)
102+
),
103+
new OA\Parameter(
104+
name: 'order',
105+
in: 'query',
106+
required: false,
107+
description: 'Order by field(s). Available fields: id, ticket_number, order_number, created. Use "-" prefix for descending order.',
108+
schema: new OA\Schema(type: 'string', example: 'created')
109+
),
110+
new OA\Parameter(
111+
name: 'expand',
112+
in: 'query',
113+
required: false,
114+
description: 'Expand relationships. Available: ticket, type, features',
115+
schema: new OA\Schema(type: 'string', example: 'ticket,type,features')
116+
),
117+
],
118+
responses: [
119+
new OA\Response(
120+
response: 200,
121+
description: 'Attendee badges retrieved successfully',
122+
content: new OA\JsonContent(ref: '#/components/schemas/PaginatedSummitAttendeeBadgesResponse')
123+
),
124+
new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"),
125+
new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"),
126+
new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"),
127+
new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"),
128+
new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"),
129+
new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"),
130+
]
131+
)]
132+
55133
/**
56134
* @param $summit_id
57135
* @return mixed
58136
*/
59-
public function getAllBySummit($summit_id){
137+
public function getAllBySummit($summit_id)
138+
{
60139

61140
$summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->getResourceServerContext())->find($summit_id);
62-
if (is_null($summit)) return $this->error404();
141+
if (is_null($summit))
142+
return $this->error404();
63143

64144
return $this->_getAll(
65-
function(){
145+
function () {
66146
return [
67-
'owner_first_name' => ['=@', '=='],
68-
'owner_last_name' => ['=@', '=='],
69-
'owner_full_name' => ['=@', '=='],
70-
'owner_email' => ['=@', '=='],
71-
'ticket_number' => ['=@', '=='],
72-
'order_number' => ['=@', '=='],
147+
'owner_first_name' => ['=@', '=='],
148+
'owner_last_name' => ['=@', '=='],
149+
'owner_full_name' => ['=@', '=='],
150+
'owner_email' => ['=@', '=='],
151+
'ticket_number' => ['=@', '=='],
152+
'order_number' => ['=@', '=='],
73153
];
74154
},
75-
function(){
155+
function () {
76156
return [
77-
'owner_first_name' => 'sometimes|string',
78-
'owner_last_name' => 'sometimes|string',
79-
'owner_full_name' => 'sometimes|string',
80-
'owner_email' => 'sometimes|string',
81-
'ticket_number' => 'sometimes|string',
82-
'order_number' => 'sometimes|string',
157+
'owner_first_name' => 'sometimes|string',
158+
'owner_last_name' => 'sometimes|string',
159+
'owner_full_name' => 'sometimes|string',
160+
'owner_email' => 'sometimes|string',
161+
'ticket_number' => 'sometimes|string',
162+
'order_number' => 'sometimes|string',
83163
];
84164
},
85-
function()
86-
{
165+
function () {
87166
return [
88167
'id',
89168
'ticket_number',
90169
'order_number',
91170
'created'
92171
];
93172
},
94-
function($filter) use($summit){
95-
if($filter instanceof Filter){
173+
function ($filter) use ($summit) {
174+
if ($filter instanceof Filter) {
96175
$filter->addFilterCondition(FilterElement::makeEqual('summit_id', $summit->getId()));
97176
}
98177
return $filter;
99178
},
100-
function(){
179+
function () {
101180
return SerializerRegistry::SerializerType_Private;
102181
}
103182
);
104183
}
105184

185+
#[OA\Get(
186+
path: '/api/v1/summits/{id}/badges/csv',
187+
operationId: 'getAllBySummitCSV',
188+
summary: 'Export all attendee badges for a summit to CSV',
189+
description: 'Exports a CSV file containing all attendee badges for a specific summit. Supports the same filtering and ordering capabilities as the standard list endpoint.',
190+
security: [['summit_badges_api_oauth2' => [SummitScopes::ReadAllSummitData]]],
191+
tags: ['Summit Badges'],
192+
parameters: [
193+
new OA\Parameter(
194+
name: 'id',
195+
in: 'path',
196+
required: true,
197+
description: 'Summit ID',
198+
schema: new OA\Schema(type: 'integer')
199+
),
200+
new OA\Parameter(
201+
name: 'filter[]',
202+
in: 'query',
203+
required: false,
204+
description: 'Filter expressions. Format: field<op>value. Available fields: owner_first_name, owner_last_name, owner_full_name, owner_email, ticket_number, order_number (all support =@, ==)',
205+
style: 'form',
206+
explode: true,
207+
schema: new OA\Schema(
208+
type: 'array',
209+
items: new OA\Items(type: 'string', example: 'owner_email=@john')
210+
)
211+
),
212+
new OA\Parameter(
213+
name: 'order',
214+
in: 'query',
215+
required: false,
216+
description: 'Order by field(s). Available fields: id, ticket_number, order_number, created',
217+
schema: new OA\Schema(type: 'string', example: '-created')
218+
),
219+
],
220+
responses: [
221+
new OA\Response(
222+
response: 200,
223+
description: 'CSV file generated successfully',
224+
content: new OA\MediaType(
225+
mediaType: 'text/csv',
226+
schema: new OA\Schema(
227+
type: 'string',
228+
format: 'binary'
229+
)
230+
)
231+
),
232+
new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"),
233+
new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"),
234+
new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"),
235+
new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"),
236+
new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"),
237+
new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"),
238+
]
239+
)]
240+
106241
/**
107242
* @param $summit_id
108243
* @return mixed
109244
*/
110-
public function getAllBySummitCSV($summit_id){
245+
public function getAllBySummitCSV($summit_id)
246+
{
111247

112248
$summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->getResourceServerContext())->find($summit_id);
113-
if (is_null($summit)) return $this->error404();
249+
if (is_null($summit))
250+
return $this->error404();
114251

115252
return $this->_getAllCSV(
116-
function(){
253+
function () {
117254
return [
118-
'owner_first_name' => ['=@', '=='],
119-
'owner_last_name' => ['=@', '=='],
120-
'owner_full_name' => ['=@', '=='],
121-
'owner_email' => ['=@', '=='],
122-
'ticket_number' => ['=@', '=='],
123-
'order_number' => ['=@', '=='],
255+
'owner_first_name' => ['=@', '=='],
256+
'owner_last_name' => ['=@', '=='],
257+
'owner_full_name' => ['=@', '=='],
258+
'owner_email' => ['=@', '=='],
259+
'ticket_number' => ['=@', '=='],
260+
'order_number' => ['=@', '=='],
124261
];
125262
},
126-
function(){
263+
function () {
127264
return [
128-
'owner_first_name' => 'sometimes|string',
129-
'owner_last_name' => 'sometimes|string',
130-
'owner_full_name' => 'sometimes|string',
131-
'owner_email' => 'sometimes|string',
132-
'ticket_number' => 'sometimes|string',
133-
'order_number' => 'sometimes|string',
265+
'owner_first_name' => 'sometimes|string',
266+
'owner_last_name' => 'sometimes|string',
267+
'owner_full_name' => 'sometimes|string',
268+
'owner_email' => 'sometimes|string',
269+
'ticket_number' => 'sometimes|string',
270+
'order_number' => 'sometimes|string',
134271
];
135272
},
136-
function()
137-
{
273+
function () {
138274
return [
139275
'id',
140276
'ticket_number',
141277
'order_number',
142278
'created'
143279
];
144280
},
145-
function($filter) use($summit){
146-
if($filter instanceof Filter){
281+
function ($filter) use ($summit) {
282+
if ($filter instanceof Filter) {
147283
$filter->addFilterCondition(FilterElement::makeEqual('summit_id', $summit->getId()));
148284
}
149285
return $filter;
150286
},
151-
function(){
287+
function () {
152288
return SerializerRegistry::SerializerType_Private;
153289
},
154-
function(){
290+
function () {
155291
return [];
156292
},
157-
function(){
293+
function () {
158294
return [];
159295
},
160296
'attendees-badges-'
@@ -163,4 +299,4 @@ function(){
163299

164300

165301

166-
}
302+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use OpenApi\Attributes as OA;
6+
7+
8+
#[OA\Schema(
9+
schema: 'SummitBadgeFeatureType',
10+
type: 'object',
11+
properties: [
12+
new OA\Property(property: 'id', type: 'integer', example: 1),
13+
new OA\Property(property: 'created', type: 'integer', example: 1),
14+
new OA\Property(property: 'last_edited', type: 'integer', example: 1),
15+
new OA\Property(property: 'name', type: 'string'),
16+
new OA\Property(property: 'description', type: 'string'),
17+
new OA\Property(property: 'template_content', type: 'string'),
18+
new OA\Property(property: 'summit_id', type: 'integer'),
19+
new OA\Property(property: 'image', type: 'string', format: 'url'),
20+
])
21+
]
22+
class SummitBadgeFeatureTypeSchema
23+
{
24+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use OpenApi\Attributes as OA;
6+
7+
8+
#[OA\Schema(
9+
schema: 'SummitBadgeType',
10+
type: 'object',
11+
properties: [
12+
new OA\Property(property: 'id', type: 'integer', example: 1),
13+
new OA\Property(property: 'created', type: 'integer', example: 1),
14+
new OA\Property(property: 'last_edited', type: 'integer', example: 1),
15+
new OA\Property(property: 'name', type: 'string'),
16+
new OA\Property(property: 'description', type: 'string'),
17+
new OA\Property(property: 'template_content', type: 'string'),
18+
new OA\Property(property: 'is_default', type: 'boolean'),
19+
new OA\Property(property: 'summit_id', type: 'integer', description: 'Summit ID, use expand=summit for full object details'),
20+
new OA\Property(
21+
property: 'access_levels',
22+
type: 'array',
23+
description: 'Array of SummitAccessLevelType IDs, use expand=access_levels for full details',
24+
items: new OA\Items(type: 'integer'),
25+
example: [1, 2, 3]
26+
),
27+
new OA\Property(
28+
property: 'badge_features',
29+
type: 'array',
30+
description: 'Array of SummitBadgeFeatureType IDs, use expand=badge_features for full details',
31+
items: new OA\Items(type: 'integer'),
32+
example: [1, 2, 3]
33+
),
34+
new OA\Property(
35+
property: 'allowed_view_types',
36+
type: 'array',
37+
description: 'Array of SummitBadgeViewType IDs, use expand=allowed_view_types for full details',
38+
items: new OA\Items(type: 'integer'),
39+
example: [1, 2, 3]
40+
),
41+
])
42+
]
43+
class SummitBadgeTypeSchema
44+
{
45+
}

0 commit comments

Comments
 (0)