Skip to content

Commit 28e31ae

Browse files
feat: Add OpenAPI documentation annotations for OAuth2UserApiController v1
1 parent 2c2445e commit 28e31ae

12 files changed

+1119
-0
lines changed

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

Lines changed: 416 additions & 0 deletions
Large diffs are not rendered by default.
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+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace App\Swagger\schemas;
4+
5+
use OAuth2\AddressClaim;
6+
use OAuth2\StandardClaims;
7+
use OpenApi\Attributes as OA;
8+
9+
#[OA\Schema(
10+
schema: 'UserInfoAddressClaim',
11+
title: 'Address Claim',
12+
description: 'OpenID Connect Address Claim (RFC 5.1.1)',
13+
type: 'object',
14+
properties: [
15+
new OA\Property(property: AddressClaim::Country, type: 'string', description: 'Country name'),
16+
new OA\Property(property: AddressClaim::StreetAddress, type: 'string', description: 'Full street address component'),
17+
new OA\Property(property: AddressClaim::Address1, type: 'string', description: 'Address line 1'),
18+
new OA\Property(property: AddressClaim::Address2, type: 'string', description: 'Address line 2'),
19+
new OA\Property(property: AddressClaim::PostalCode, type: 'string', description: 'Zip code or postal code'),
20+
new OA\Property(property: AddressClaim::Region, type: 'string', description: 'State, province, or region'),
21+
new OA\Property(property: AddressClaim::Locality, type: 'string', description: 'City or locality'),
22+
new OA\Property(property: AddressClaim::Formatted, type: 'string', description: 'Full mailing address, formatted for display'),
23+
]
24+
)]
25+
class UserInfoAddressClaimSchema
26+
{
27+
}
28+
29+
#[OA\Schema(
30+
schema: 'UserInfoResponse',
31+
title: 'UserInfo Response',
32+
description: 'OpenID Connect UserInfo endpoint response. Claims returned depend on the requested scopes (profile, email, address).',
33+
type: 'object',
34+
required: [StandardClaims::SubjectIdentifier, 'aud'],
35+
properties: [
36+
// JWT standard claims
37+
new OA\Property(property: StandardClaims::SubjectIdentifier, type: 'string', description: 'Subject identifier for the End-User'),
38+
new OA\Property(property: 'aud', type: 'string', description: 'Audience (client ID)'),
39+
40+
// Profile scope claims
41+
new OA\Property(property: StandardClaims::Name, type: 'string', description: 'Full name'),
42+
new OA\Property(property: StandardClaims::GivenName, type: 'string', description: 'First name'),
43+
new OA\Property(property: StandardClaims::PreferredUserName, type: 'string', description: 'Preferred username'),
44+
new OA\Property(property: StandardClaims::FamilyName, type: 'string', description: 'Last name'),
45+
new OA\Property(property: StandardClaims::NickName, type: 'string', description: 'Casual name or identifier'),
46+
new OA\Property(property: StandardClaims::Picture, type: 'string', format: 'uri', description: 'Profile picture URL'),
47+
new OA\Property(property: StandardClaims::Birthdate, type: 'string', description: 'Date of birth'),
48+
new OA\Property(property: StandardClaims::Gender, type: 'string', description: 'Gender'),
49+
new OA\Property(property: StandardClaims::GenderSpecify, type: 'string', description: 'Gender specification'),
50+
new OA\Property(property: StandardClaims::Locale, type: 'string', description: 'Preferred language'),
51+
new OA\Property(property: StandardClaims::Bio, type: 'string', description: 'User biography'),
52+
new OA\Property(property: StandardClaims::StatementOfInterest, type: 'string', description: 'Statement of interest'),
53+
new OA\Property(property: StandardClaims::Irc, type: 'string', description: 'IRC handle'),
54+
new OA\Property(property: StandardClaims::GitHubUser, type: 'string', description: 'GitHub username'),
55+
new OA\Property(property: StandardClaims::WeChatUser, type: 'string', description: 'WeChat username'),
56+
new OA\Property(property: StandardClaims::TwitterName, type: 'string', description: 'Twitter handle'),
57+
new OA\Property(property: StandardClaims::LinkedInProfile, type: 'string', description: 'LinkedIn profile URL'),
58+
new OA\Property(property: StandardClaims::Company, type: 'string', description: 'Company name'),
59+
new OA\Property(property: StandardClaims::JobTitle, type: 'string', description: 'Job title'),
60+
new OA\Property(property: StandardClaims::ShowPicture, type: 'boolean', description: 'Show photo in public profile'),
61+
new OA\Property(property: StandardClaims::ShowBio, type: 'boolean', description: 'Show bio in public profile'),
62+
new OA\Property(property: StandardClaims::ShowSocialMediaInfo, type: 'boolean', description: 'Show social media info in public profile'),
63+
new OA\Property(property: StandardClaims::ShowFullName, type: 'boolean', description: 'Show full name in public profile'),
64+
new OA\Property(property: StandardClaims::AllowChatWithMe, type: 'boolean', description: 'Allow chat in public profile'),
65+
new OA\Property(property: StandardClaims::ShowTelephoneNumber, type: 'boolean', description: 'Show telephone in public profile'),
66+
new OA\Property(
67+
property: StandardClaims::Groups,
68+
type: 'array',
69+
items: new OA\Items(ref: '#/components/schemas/Group'),
70+
description: 'User groups'
71+
),
72+
73+
// Email scope claims
74+
new OA\Property(property: StandardClaims::Email, type: 'string', format: 'email', description: 'Primary email address'),
75+
new OA\Property(property: StandardClaims::SecondEmail, type: 'string', format: 'email', description: 'Secondary email address'),
76+
new OA\Property(property: StandardClaims::ThirdEmail, type: 'string', format: 'email', description: 'Tertiary email address'),
77+
new OA\Property(property: StandardClaims::EmailVerified, type: 'boolean', description: 'Whether the primary email is verified'),
78+
new OA\Property(property: StandardClaims::ShowEmail, type: 'boolean', description: 'Whether to show the email or not'),
79+
80+
// Address scope claims
81+
new OA\Property(
82+
property: StandardClaims::Address,
83+
ref: '#/components/schemas/UserInfoAddressClaim',
84+
description: 'End-User preferred postal address (address scope)'
85+
),
86+
]
87+
)]
88+
class UserInfoResponseSchema
89+
{
90+
}

app/Swagger/Models/UserSchema.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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(ref: '#/components/schemas/Group'),
56+
description: 'User groups (expandable with expand=groups)'
57+
),
58+
]
59+
)
60+
]
61+
)]
62+
class UserSchema
63+
{
64+
}
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: 'PaginatedUserResponseSchema',
9+
type: 'object',
10+
allOf: [
11+
new OA\Schema(ref: '#/components/schemas/PaginateDataSchemaResponse'),
12+
new OA\Schema(
13+
type: 'object',
14+
properties: [
15+
new OA\Property(
16+
property: 'data',
17+
type: 'array',
18+
items: new OA\Items(ref: '#/components/schemas/User')
19+
)
20+
]
21+
)
22+
]
23+
)]
24+
class PaginatedUserResponseSchema
25+
{
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php namespace App\Swagger\schemas;
2+
3+
/**
4+
* Copyright 2025 OpenStack Foundation
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
**/
15+
16+
use OpenApi\Attributes as OA;
17+
18+
#[OA\Schema(
19+
schema: 'CreateUserRequest',
20+
title: 'Create User Request',
21+
description: 'Request body for creating a new user. Only email is required, all other fields are optional.',
22+
type: 'object',
23+
required: ['email'],
24+
allOf: [
25+
new OA\Schema(ref: '#/components/schemas/UserFields')
26+
]
27+
)]
28+
class CreateUserRequestSchema
29+
{
30+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php namespace App\Swagger\schemas;
2+
3+
/**
4+
* Copyright 2025 OpenStack Foundation
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
**/
15+
16+
use OpenApi\Attributes as OA;
17+
18+
#[OA\Schema(
19+
schema: 'UpdateUserGroupsRequest',
20+
title: 'Update User Groups Request',
21+
description: 'Request body for updating user group assignments',
22+
type: 'object',
23+
required: ['groups'],
24+
properties: [
25+
new OA\Property(
26+
property: 'groups',
27+
type: 'array',
28+
items: new OA\Items(type: 'integer'),
29+
description: 'Array of group IDs to assign to the user',
30+
example: [1, 2, 3]
31+
)
32+
]
33+
)]
34+
class UpdateUserGroupsRequestSchema
35+
{
36+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php namespace App\Swagger\schemas;
2+
3+
/**
4+
* Copyright 2025 OpenStack Foundation
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
**/
15+
16+
use OpenApi\Attributes as OA;
17+
18+
#[OA\Schema(
19+
schema: 'UpdateUserPicRequest',
20+
title: 'Update User Profile Picture Request',
21+
description: 'Request body for uploading a user profile picture',
22+
type: 'object',
23+
required: ['file'],
24+
properties: [
25+
new OA\Property(
26+
property: 'file',
27+
description: 'Profile picture image file',
28+
type: 'string',
29+
format: 'binary'
30+
),
31+
]
32+
)]
33+
class UpdateUserPicRequestSchema
34+
{
35+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php namespace App\Swagger\schemas;
2+
3+
/**
4+
* Copyright 2025 OpenStack Foundation
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
**/
15+
16+
use OpenApi\Attributes as OA;
17+
18+
#[OA\Schema(
19+
schema: 'UpdateUserRequest',
20+
title: 'Update User Request',
21+
description: 'Request body for updating a user. All fields are optional. Note: groups, email_verified, and active fields are automatically removed from non-admin requests.',
22+
type: 'object',
23+
allOf: [
24+
new OA\Schema(ref: '#/components/schemas/UserFields')
25+
]
26+
)]
27+
class UpdateUserRequestSchema
28+
{
29+
}

0 commit comments

Comments
 (0)