mark oneOf form parameters as optional (#16512)

This commit is contained in:
William Cheng 2023-09-06 17:27:44 +08:00 committed by GitHub
parent 3817e40f47
commit d1808405ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 165 additions and 2 deletions

View File

@ -6943,6 +6943,8 @@ public class DefaultCodegen implements CodegenConfig {
// https://github.com/OpenAPITools/openapi-generator/issues/10415
addProperties(properties, allRequired, schema, new HashSet<>());
boolean isOneOfOrAnyOf = ModelUtils.isOneOf(schema) || ModelUtils.isAnyOf(schema);
if (!properties.isEmpty()) {
for (Map.Entry<String, Schema> entry : properties.entrySet()) {
CodegenParameter codegenParameter;
@ -6952,8 +6954,12 @@ public class DefaultCodegen implements CodegenConfig {
Schema propertySchema = entry.getValue();
codegenParameter = fromFormProperty(propertyName, propertySchema, imports);
if (isOneOfOrAnyOf) {
// for oneOf/anyOf, mark all the properties collected from the sub-schemas as optional
// so that users can choose which property to include in the form parameters
codegenParameter.required = false;
} else if (!codegenParameter.required && schema.getRequired() != null) {
// Set 'required' flag defined in the schema element
if (!codegenParameter.required && schema.getRequired() != null) {
codegenParameter.required = schema.getRequired().contains(entry.getKey());
} else if (!codegenParameter.required) {
// Set 'required' flag for properties declared inside the allOf

View File

@ -292,4 +292,32 @@ public class Swift5ClientCodegenTest {
}
}
@Test(description = "optional form parameters when using oneOf schema", enabled = true)
public void oneOfFormParameterTest() {
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_15511.yaml");
final DefaultCodegen codegen = new Swift5ClientCodegen();
codegen.setOpenAPI(openAPI);
codegen.processOpts();
final String path = "/as/token.oauth2";
final Operation p = openAPI.getPaths().get(path).getPost();
final CodegenOperation op = codegen.fromOperation(path, "post", p, null);
Assert.assertEquals(op.formParams.size(), 6);
Assert.assertEquals(op.formParams.get(0).baseName, "client_id");
Assert.assertEquals(op.formParams.get(1).baseName, "grant_type");
Assert.assertEquals(op.formParams.get(2).baseName, "password");
Assert.assertEquals(op.formParams.get(3).baseName, "scope");
Assert.assertEquals(op.formParams.get(4).baseName, "username");
Assert.assertEquals(op.formParams.get(5).baseName, "refresh_token");
Assert.assertEquals(op.formParams.get(0).required, false);
Assert.assertEquals(op.formParams.get(1).required, false);
Assert.assertEquals(op.formParams.get(2).required, false);
Assert.assertEquals(op.formParams.get(3).required, false);
Assert.assertEquals(op.formParams.get(4).required, false);
Assert.assertEquals(op.formParams.get(5).required, false);
}
}

View File

@ -0,0 +1,129 @@
openapi: 3.0.3
info:
title: Auth Server Client API
description: |-
foobarbaz
version: 1.0.0
tags:
- name: auth
description: Auth Server Client APIs for obtaining, refreshing and revoking a token
paths:
/as/token.oauth2:
post:
tags:
- auth
summary: Obtains a new token from Auth server
requestBody:
content:
application/x-www-form-urlencoded; charset=utf-8:
schema:
oneOf:
- $ref: '#/components/schemas/LoginRequestModel'
- $ref: '#/components/schemas/TokenRefreshRequestModel'
required: true
responses:
'200':
description: Successful operation
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/LoginResponseModel'
- $ref: '#/components/schemas/TokenRefreshResponseModel'
default:
description: An error occured
content:
application/json:
schema:
$ref: '#/components/schemas/AuthResponseError'
components:
schemas:
LoginResponseModel:
type: object
properties:
expires_in:
type: integer
format: int32
access_token:
type: string
refresh_token:
type: string
token_type:
type: string
required:
[expires_in, access_token, refresh_token]
TokenRefreshResponseModel:
type: object
description: Be aware, that we may either receive a new refresh token in the response or not. In case where we do not receive a new refresh token we must use the refresh token from the old token for subsequent token refreshs.
properties:
expires_in:
type: integer
format: int32
access_token:
type: string
refresh_token:
type: string
token_type:
type: string
required:
[expires_in, access_token]
LoginRequestModel:
type: object
properties:
client_id:
type: string
grant_type:
type: string
enum: ["refresh_token", "password"]
password:
type: string
scope:
type: string
username:
type: string
required:
[client_id, grant_type, password, scope, username]
TokenRefreshRequestModel:
type: object
properties:
grant_type:
type: string
enum: ["refresh_token", "password"]
refresh_token:
type: string
required:
[grant_type, refresh_token]
AuthResponseError:
type: object
properties:
error_description:
type: string
error:
type: string
enum: ["invalid_request", "invalid_client", "invalid_grant", "invalid_scope", "unauthorized_client", "unsupported_grant_type"]
x-enum-descriptions:
- 'Request is missing a parameter or contains an unsupported parameter of repeats parameters.'
- 'Client authentication fails due to an invalid client id or secret.'
- 'Authorization code or password is invalid or expired.'
- 'Invalid scope for the given access token.'
- 'Client is not authorized for requested grant type.'
- 'Given grant type is unsupported.'
x-enum-varnames:
- INVALID_REQUEST
- INVALID_CLIENT
- INVALID_GRANT
- INVALID_SCOPE
- UNAUTHORIZED_CLIENT
- UNSUPPORTED_GRANT_TYPE
errors:
type: array
items:
$ref: "#/components/schemas/AuthErrorDescription"
required:
[error_description, error]
AuthErrorDescription:
type: object
properties:
description:
type: string