Skip to content

Commit bba5793

Browse files
feat: Add OpenAPI documentation on controller OAuth2UserApiController v2 routes
Signed-off-by: matiasperrone-exo <matias.perrone@exomindset.co>
1 parent 7f63bee commit bba5793

File tree

6 files changed

+335
-0
lines changed

6 files changed

+335
-0
lines changed

app/Http/Controllers/Api/OAuth2/OAuth2UserApiController.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@
3737
use OAuth2\ResourceServer\IUserService;
3838
use Utils\Http\HttpContentType;
3939
use Utils\Services\ILogService;
40+
use App\libs\OAuth2\IUserScopes;
4041
use Exception;
42+
use OpenApi\Attributes as OA;
4143
use OpenId\Services\IUserService as IOpenIdUserService;
44+
use Symfony\Component\HttpFoundation\Response as HttpResponse;
4245
/**
4346
* Class OAuth2UserApiController
4447
* @package App\Http\Controllers\Api\OAuth2
@@ -336,6 +339,48 @@ public function get($id)
336339
* @param $id
337340
* @return \Illuminate\Http\JsonResponse|mixed
338341
*/
342+
#[OA\Get(
343+
path: '/api/v2/users/{id}',
344+
summary: 'Get a user by ID',
345+
operationId: 'getUserByIdV2',
346+
tags: ['Users'],
347+
security: [
348+
['user_oauth2' => [
349+
IUserScopes::ReadAll,
350+
]],
351+
],
352+
parameters: [
353+
new OA\Parameter(
354+
name: 'id',
355+
description: 'User ID',
356+
in: 'path',
357+
required: true,
358+
schema: new OA\Schema(type: 'integer')
359+
),
360+
new OA\Parameter(
361+
name: 'expand',
362+
description: 'Expand relations: groups',
363+
in: 'query',
364+
required: false,
365+
schema: new OA\Schema(type: 'string')
366+
),
367+
],
368+
responses: [
369+
new OA\Response(
370+
response: HttpResponse::HTTP_OK,
371+
description: 'OK',
372+
content: new OA\JsonContent(ref: '#/components/schemas/User')
373+
),
374+
new OA\Response(
375+
response: HttpResponse::HTTP_NOT_FOUND,
376+
description: 'Not Found'
377+
),
378+
new OA\Response(
379+
response: HttpResponse::HTTP_INTERNAL_SERVER_ERROR,
380+
description: 'Server Error'
381+
),
382+
]
383+
)]
339384
public function getV2($id)
340385
{
341386
return $this->processRequest(function() use($id) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use OpenApi\Attributes as OA;
6+
7+
#[OA\Schema(
8+
schema: 'BaseUser',
9+
title: 'Base User',
10+
description: 'Base User serialized representation',
11+
type: 'object',
12+
allOf: [
13+
new OA\Schema(ref: '#/components/schemas/Base'),
14+
new OA\Schema(
15+
type: 'object',
16+
properties: [
17+
new OA\Property(property: 'first_name', type: 'string', description: 'First name', example: 'John'),
18+
new OA\Property(property: 'last_name', type: 'string', description: 'Last name', example: 'Doe'),
19+
new OA\Property(property: 'pic', type: 'string', format: 'uri', description: 'Profile picture URL'),
20+
]
21+
)
22+
]
23+
)]
24+
class BaseUserSchema
25+
{
26+
}

app/Swagger/Models/GroupSchema.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use OpenApi\Attributes as OA;
6+
7+
#[OA\Schema(
8+
schema: 'Group',
9+
title: 'Group',
10+
description: 'Group serialized representation',
11+
type: 'object',
12+
allOf: [
13+
new OA\Schema(ref: '#/components/schemas/Base'),
14+
new OA\Schema(
15+
type: 'object',
16+
properties: [
17+
new OA\Property(property: 'name', type: 'string', description: 'Group name'),
18+
new OA\Property(property: 'slug', type: 'string', description: 'Group slug'),
19+
new OA\Property(property: 'active', type: 'boolean', description: 'Whether the group is active'),
20+
new OA\Property(property: 'default', type: 'boolean', description: 'Whether the group is a default group'),
21+
]
22+
)
23+
]
24+
)]
25+
class GroupSchema
26+
{
27+
}

app/Swagger/Models/UserSchema.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use OpenApi\Attributes as OA;
6+
7+
#[OA\Schema(
8+
schema: 'User',
9+
title: 'User',
10+
description: 'User serialized representation (private)',
11+
type: 'object',
12+
allOf: [
13+
new OA\Schema(ref: '#/components/schemas/BaseUser'),
14+
new OA\Schema(
15+
type: 'object',
16+
properties: [
17+
new OA\Property(property: 'email', type: 'string', format: 'email', description: 'Primary email address'),
18+
new OA\Property(property: 'identifier', type: 'string', description: 'User unique identifier string'),
19+
new OA\Property(property: 'email_verified', type: 'boolean', description: 'Whether the primary email is verified'),
20+
new OA\Property(property: 'bio', type: 'string', nullable: true, description: 'User biography'),
21+
new OA\Property(property: 'address1', type: 'string', description: 'Address line 1'),
22+
new OA\Property(property: 'address2', type: 'string', nullable: true, description: 'Address line 2'),
23+
new OA\Property(property: 'city', type: 'string', description: 'City'),
24+
new OA\Property(property: 'state', type: 'string', description: 'State or province'),
25+
new OA\Property(property: 'post_code', type: 'string', description: 'Postal code'),
26+
new OA\Property(property: 'country_iso_code', type: 'string', description: 'ISO country code'),
27+
new OA\Property(property: 'second_email', type: 'string', format: 'email', nullable: true, description: 'Secondary email address'),
28+
new OA\Property(property: 'third_email', type: 'string', format: 'email', nullable: true, description: 'Tertiary email address'),
29+
new OA\Property(property: 'gender', type: 'string', nullable: true, description: 'Gender'),
30+
new OA\Property(property: 'gender_specify', type: 'string', nullable: true, description: 'Gender specification'),
31+
new OA\Property(property: 'statement_of_interest', type: 'string', nullable: true, description: 'Statement of interest'),
32+
new OA\Property(property: 'irc', type: 'string', nullable: true, description: 'IRC handle'),
33+
new OA\Property(property: 'linked_in_profile', type: 'string', nullable: true, description: 'LinkedIn profile URL'),
34+
new OA\Property(property: 'github_user', type: 'string', nullable: true, description: 'GitHub username'),
35+
new OA\Property(property: 'wechat_user', type: 'string', nullable: true, description: 'WeChat username'),
36+
new OA\Property(property: 'twitter_name', type: 'string', nullable: true, description: 'Twitter handle'),
37+
new OA\Property(property: 'language', type: 'string', nullable: true, description: 'Preferred language'),
38+
new OA\Property(property: 'birthday', type: 'integer', nullable: true, description: 'Date of birth (epoch)'),
39+
new OA\Property(property: 'phone_number', type: 'string', nullable: true, description: 'Phone number'),
40+
new OA\Property(property: 'company', type: 'string', nullable: true, description: 'Company name'),
41+
new OA\Property(property: 'job_title', type: 'string', nullable: true, description: 'Job title'),
42+
new OA\Property(property: 'spam_type', type: 'string', description: 'Spam classification', enum: ['None', 'Spam', 'Ham']),
43+
new OA\Property(property: 'last_login_date', type: 'integer', nullable: true, description: 'Last login date (epoch)'),
44+
new OA\Property(property: 'active', type: 'boolean', description: 'Whether the user account is active'),
45+
new OA\Property(property: 'public_profile_show_photo', type: 'boolean', description: 'Show photo in public profile'),
46+
new OA\Property(property: 'public_profile_show_fullname', type: 'boolean', description: 'Show full name in public profile'),
47+
new OA\Property(property: 'public_profile_show_email', type: 'boolean', description: 'Show email in public profile'),
48+
new OA\Property(property: 'public_profile_show_social_media_info', type: 'boolean', description: 'Show social media info in public profile'),
49+
new OA\Property(property: 'public_profile_show_bio', type: 'boolean', description: 'Show bio in public profile'),
50+
new OA\Property(property: 'public_profile_allow_chat_with_me', type: 'boolean', description: 'Allow chat in public profile'),
51+
new OA\Property(property: 'public_profile_show_telephone_number', type: 'boolean', description: 'Show telephone in public profile'),
52+
new OA\Property(
53+
property: 'groups',
54+
type: 'array',
55+
items: new OA\Items(oneOf: [
56+
new OA\Schema(type: 'string', description: 'Group slug (when not expanded)'),
57+
new OA\Schema(ref: '#/components/schemas/Group', description:'Group object (when expanded)'),
58+
]),
59+
description: 'User groups (expandable with expand=groups)'
60+
),
61+
]
62+
)
63+
]
64+
)]
65+
class UserSchema
66+
{
67+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use OpenApi\Attributes as OA;
6+
7+
#[OA\Schema(
8+
schema: 'CreateUser',
9+
title: 'Create User',
10+
description: 'Request body for creating a new user',
11+
required: ['email'],
12+
type: 'object',
13+
properties: [
14+
new OA\Property(property: 'first_name', type: 'string', description: 'First name'),
15+
new OA\Property(property: 'last_name', type: 'string', description: 'Last name'),
16+
new OA\Property(property: 'email', type: 'string', format: 'email', description: 'Primary email address'),
17+
new OA\Property(property: 'identifier', type: 'string', description: 'User unique identifier string'),
18+
new OA\Property(property: 'bio', type: 'string', nullable: true, description: 'User biography'),
19+
new OA\Property(property: 'address1', type: 'string', nullable: true, description: 'Address line 1'),
20+
new OA\Property(property: 'address2', type: 'string', nullable: true, description: 'Address line 2'),
21+
new OA\Property(property: 'city', type: 'string', nullable: true, description: 'City'),
22+
new OA\Property(property: 'state', type: 'string', nullable: true, description: 'State or province'),
23+
new OA\Property(property: 'post_code', type: 'string', nullable: true, description: 'Postal code'),
24+
new OA\Property(property: 'country_iso_code', type: 'string', nullable: true, description: 'ISO 3166-1 alpha-2 country code'),
25+
new OA\Property(property: 'second_email', type: 'string', format: 'email', nullable: true, description: 'Secondary email address'),
26+
new OA\Property(property: 'third_email', type: 'string', format: 'email', nullable: true, description: 'Tertiary email address'),
27+
new OA\Property(property: 'gender', type: 'string', nullable: true, description: 'Gender'),
28+
new OA\Property(property: 'statement_of_interest', type: 'string', nullable: true, description: 'Statement of interest'),
29+
new OA\Property(property: 'irc', type: 'string', nullable: true, description: 'IRC handle'),
30+
new OA\Property(property: 'linked_in_profile', type: 'string', nullable: true, description: 'LinkedIn profile URL'),
31+
new OA\Property(property: 'github_user', type: 'string', nullable: true, description: 'GitHub username'),
32+
new OA\Property(property: 'wechat_user', type: 'string', nullable: true, description: 'WeChat username'),
33+
new OA\Property(property: 'twitter_name', type: 'string', nullable: true, description: 'Twitter handle'),
34+
new OA\Property(property: 'language', type: 'string', nullable: true, description: 'Preferred language'),
35+
new OA\Property(property: 'birthday', type: 'integer', nullable: true, description: 'Date of birth (epoch)'),
36+
new OA\Property(property: 'password', type: 'string', format: 'password', description: 'Password'),
37+
new OA\Property(property: 'password_confirmation', type: 'string', format: 'password', description: 'Password confirmation (required when password is provided)'),
38+
new OA\Property(property: 'phone_number', type: 'string', nullable: true, description: 'Phone number'),
39+
new OA\Property(property: 'company', type: 'string', nullable: true, description: 'Company name'),
40+
new OA\Property(property: 'job_title', type: 'string', nullable: true, maxLength: 200, description: 'Job title'),
41+
new OA\Property(property: 'email_verified', type: 'boolean', nullable: true, description: 'Whether the primary email is verified (admin only)'),
42+
new OA\Property(property: 'active', type: 'boolean', nullable: true, description: 'Whether the user account is active (admin only)'),
43+
new OA\Property(property: 'groups', type: 'array', items: new OA\Items(type: 'integer'), description: 'Group IDs to assign (admin only)'),
44+
new OA\Property(property: 'public_profile_show_photo', type: 'boolean', description: 'Show photo in public profile'),
45+
new OA\Property(property: 'public_profile_show_fullname', type: 'boolean', description: 'Show full name in public profile'),
46+
new OA\Property(property: 'public_profile_show_email', type: 'boolean', description: 'Show email in public profile'),
47+
new OA\Property(property: 'public_profile_show_social_media_info', type: 'boolean', description: 'Show social media info in public profile'),
48+
new OA\Property(property: 'public_profile_show_bio', type: 'boolean', description: 'Show bio in public profile'),
49+
new OA\Property(property: 'public_profile_allow_chat_with_me', type: 'boolean', description: 'Allow chat in public profile'),
50+
new OA\Property(property: 'public_profile_show_telephone_number', type: 'boolean', description: 'Show telephone in public profile'),
51+
]
52+
)]
53+
class CreateUserSchema
54+
{
55+
}
56+
57+
#[OA\Schema(
58+
schema: 'UpdateUser',
59+
title: 'Update User',
60+
description: 'Request body for updating a user',
61+
type: 'object',
62+
properties: [
63+
new OA\Property(property: 'first_name', type: 'string', description: 'First name'),
64+
new OA\Property(property: 'last_name', type: 'string', description: 'Last name'),
65+
new OA\Property(property: 'email', type: 'string', format: 'email', description: 'Primary email address'),
66+
new OA\Property(property: 'identifier', type: 'string', description: 'User unique identifier string'),
67+
new OA\Property(property: 'bio', type: 'string', nullable: true, description: 'User biography'),
68+
new OA\Property(property: 'address1', type: 'string', nullable: true, description: 'Address line 1'),
69+
new OA\Property(property: 'address2', type: 'string', nullable: true, description: 'Address line 2'),
70+
new OA\Property(property: 'city', type: 'string', nullable: true, description: 'City'),
71+
new OA\Property(property: 'state', type: 'string', nullable: true, description: 'State or province'),
72+
new OA\Property(property: 'post_code', type: 'string', nullable: true, description: 'Postal code'),
73+
new OA\Property(property: 'country_iso_code', type: 'string', nullable: true, description: 'ISO 3166-1 alpha-2 country code'),
74+
new OA\Property(property: 'second_email', type: 'string', format: 'email', nullable: true, description: 'Secondary email address'),
75+
new OA\Property(property: 'third_email', type: 'string', format: 'email', nullable: true, description: 'Tertiary email address'),
76+
new OA\Property(property: 'gender', type: 'string', nullable: true, description: 'Gender'),
77+
new OA\Property(property: 'gender_specify', type: 'string', nullable: true, description: 'Gender specification'),
78+
new OA\Property(property: 'statement_of_interest', type: 'string', nullable: true, description: 'Statement of interest'),
79+
new OA\Property(property: 'irc', type: 'string', nullable: true, description: 'IRC handle'),
80+
new OA\Property(property: 'linked_in_profile', type: 'string', nullable: true, description: 'LinkedIn profile URL'),
81+
new OA\Property(property: 'github_user', type: 'string', nullable: true, description: 'GitHub username'),
82+
new OA\Property(property: 'wechat_user', type: 'string', nullable: true, description: 'WeChat username'),
83+
new OA\Property(property: 'twitter_name', type: 'string', nullable: true, description: 'Twitter handle'),
84+
new OA\Property(property: 'language', type: 'string', nullable: true, description: 'Preferred language'),
85+
new OA\Property(property: 'birthday', type: 'integer', nullable: true, description: 'Date of birth (epoch)'),
86+
new OA\Property(property: 'password', type: 'string', format: 'password', description: 'New password'),
87+
new OA\Property(property: 'password_confirmation', type: 'string', format: 'password', description: 'Password confirmation (required when password is provided)'),
88+
new OA\Property(property: 'current_password', type: 'string', format: 'password', description: 'Current password (required when changing password for non-admin users)'),
89+
new OA\Property(property: 'phone_number', type: 'string', nullable: true, description: 'Phone number'),
90+
new OA\Property(property: 'company', type: 'string', nullable: true, description: 'Company name'),
91+
new OA\Property(property: 'job_title', type: 'string', nullable: true, maxLength: 200, description: 'Job title'),
92+
new OA\Property(property: 'email_verified', type: 'boolean', nullable: true, description: 'Whether the primary email is verified (admin only)'),
93+
new OA\Property(property: 'active', type: 'boolean', nullable: true, description: 'Whether the user account is active (admin only)'),
94+
new OA\Property(property: 'groups', type: 'array', items: new OA\Items(type: 'integer'), description: 'Group IDs to assign (admin only)'),
95+
new OA\Property(property: 'public_profile_show_photo', type: 'boolean', description: 'Show photo in public profile'),
96+
new OA\Property(property: 'public_profile_show_fullname', type: 'boolean', description: 'Show full name in public profile'),
97+
new OA\Property(property: 'public_profile_show_email', type: 'boolean', description: 'Show email in public profile'),
98+
new OA\Property(property: 'public_profile_show_social_media_info', type: 'boolean', description: 'Show social media info in public profile'),
99+
new OA\Property(property: 'public_profile_show_bio', type: 'boolean', description: 'Show bio in public profile'),
100+
new OA\Property(property: 'public_profile_allow_chat_with_me', type: 'boolean', description: 'Allow chat in public profile'),
101+
new OA\Property(property: 'public_profile_show_telephone_number', type: 'boolean', description: 'Show telephone in public profile'),
102+
]
103+
)]
104+
class UpdateUserSchema
105+
{
106+
}
107+
108+
#[OA\Schema(
109+
schema: 'UpdateUserPic',
110+
title: 'Update User Profile Picture',
111+
description: 'Request body for updating user profile picture',
112+
required: ['file'],
113+
type: 'object',
114+
properties: [
115+
new OA\Property(
116+
property: 'file',
117+
type: 'string',
118+
format: 'binary',
119+
description: 'Profile picture file'
120+
),
121+
]
122+
)]
123+
class UpdateUserPicSchema
124+
{
125+
}
126+
127+
#[OA\Schema(
128+
schema: 'UpdateUserGroups',
129+
title: 'Update User Groups',
130+
description: 'Request body for updating user group assignments',
131+
required: ['groups'],
132+
type: 'object',
133+
properties: [
134+
new OA\Property(
135+
property: 'groups',
136+
type: 'array',
137+
items: new OA\Items(type: 'integer'),
138+
description: 'Array of group IDs to assign to the user'
139+
),
140+
]
141+
)]
142+
class UpdateUserGroupsSchema
143+
{
144+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use App\libs\OAuth2\IUserScopes;
6+
use OpenApi\Attributes as OA;
7+
8+
#[
9+
OA\SecurityScheme(
10+
type: 'oauth2',
11+
securityScheme: 'user_oauth2',
12+
flows: [
13+
new OA\Flow(
14+
flow: 'authorizationCode',
15+
authorizationUrl: '/oauth2/auth',
16+
tokenUrl: '/oauth2/token',
17+
scopes: [
18+
IUserScopes::ReadAll => 'Read All Users Data',
19+
],
20+
),
21+
],
22+
)
23+
]
24+
class UsersOAuth2Schema
25+
{
26+
}

0 commit comments

Comments
 (0)