Skip to content

Commit 3d00c4b

Browse files
stcarrezjaumard
authored andcommitted
OpenAPITools#1043 - [Ada] Operation security scopes are ignored when generating the server (OpenAPITools#1044)
* [Ada] Operation security scopes are ignored when generating the server (OpenAPITools#1043) - Update fromOperation() to keep the operation required scopes for each auth method and store that information in the x-scopes vendor extensions attribute - Update postProcessOperationsWithModels() to process the operation required scopes and build a list of authMethods which only contain the required scopes for the operation and store these authMethods in the x-auth-scopes attribute. - Update postProcessAuthMethod() to handle the logic of filtering and building the operation authMethod (new instances are created because we must not modify the global authMethod definitions) - Update the Ada server templates to use the x-auth-scopes instead of authMethods Add a URL prefix parameter for the Ada server instantiation * Fix the Ada server template to use the x-auth-scopes for operation scopes
1 parent 4819e84 commit 3d00c4b

File tree

3 files changed

+83
-9
lines changed

3 files changed

+83
-9
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractAdaCodegen.java

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import io.swagger.v3.oas.models.media.ArraySchema;
2525
import io.swagger.v3.oas.models.media.Schema;
2626
import io.swagger.v3.oas.models.responses.ApiResponse;
27+
import io.swagger.v3.oas.models.security.SecurityRequirement;
28+
import io.swagger.v3.oas.models.security.SecurityScheme;
2729
import org.openapitools.codegen.CodegenConfig;
2830
import org.openapitools.codegen.CodegenConstants;
2931
import org.openapitools.codegen.CodegenModel;
@@ -414,9 +416,38 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
414416
}
415417
}
416418
}
419+
420+
// Add a vendor extension attribute that provides a map of auth methods and the scopes
421+
// which are expected by the operation. This map is then used by postProcessOperationsWithModels
422+
// to build another vendor extension that provides a subset of the auth methods with only
423+
// the scopes required by the operation.
424+
final List<SecurityRequirement> securities = operation.getSecurity();
425+
if (securities != null && securities.size() > 0) {
426+
final Map<String, SecurityScheme> securitySchemes = openAPI.getComponents() != null ? openAPI.getComponents().getSecuritySchemes() : null;
427+
final List<SecurityRequirement> globalSecurities = openAPI.getSecurity();
428+
429+
Map<String, List<String>> scopes = getAuthScopes(securities, securitySchemes);
430+
if (scopes.isEmpty() && globalSecurities != null) {
431+
scopes = getAuthScopes(globalSecurities, securitySchemes);
432+
}
433+
op.vendorExtensions.put("x-scopes", scopes);
434+
}
417435
return op;
418436
}
419437

438+
private Map<String, List<String>> getAuthScopes(List<SecurityRequirement> securities, Map<String, SecurityScheme> securitySchemes) {
439+
final Map<String, List<String>> scopes = new HashMap<>();
440+
for (SecurityRequirement requirement : securities) {
441+
for (String key : requirement.keySet()) {
442+
SecurityScheme securityScheme = securitySchemes.get(key);
443+
if (securityScheme != null) {
444+
scopes.put(key, requirement.get(key));
445+
}
446+
}
447+
}
448+
return scopes;
449+
}
450+
420451
@SuppressWarnings("unchecked")
421452
@Override
422453
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
@@ -449,7 +480,14 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
449480
p.dataType = "Swagger.File_Part_Type";
450481
}
451482
}
452-
postProcessAuthMethod(op1.authMethods);
483+
484+
// Given the operation scopes and the auth methods, build a list of auth methods that only
485+
// describe the auth methods and scopes required by the operation.
486+
final Map<String, List<String>> scopes = (Map<String, List<String>>) op1.vendorExtensions.get("x-scopes");
487+
List<CodegenSecurity> opScopes = postProcessAuthMethod(op1.authMethods, scopes);
488+
if (opScopes != null) {
489+
op1.vendorExtensions.put("x-auth-scopes", opScopes);
490+
}
453491

454492
/*
455493
* Scan the path parameter to construct a x-path-index that tells the index of
@@ -584,7 +622,7 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
584622
* Collect the scopes to generate unique identifiers for each of them.
585623
*/
586624
List<CodegenSecurity> authMethods = (List<CodegenSecurity>) objs.get("authMethods");
587-
postProcessAuthMethod(authMethods);
625+
postProcessAuthMethod(authMethods, null);
588626

589627
return super.postProcessSupportingFileData(objs);
590628
}
@@ -593,8 +631,11 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
593631
* Collect the scopes to generate a unique identifier for each of them.
594632
*
595633
* @param authMethods the auth methods with their scopes.
634+
* @param scopes the optional auth methods and scopes required by an operation
635+
* @return the authMethods to be used by the operation with its required scopes.
596636
*/
597-
private void postProcessAuthMethod(List<CodegenSecurity> authMethods) {
637+
private List<CodegenSecurity> postProcessAuthMethod(List<CodegenSecurity> authMethods, Map<String, List<String>> scopes) {
638+
List<CodegenSecurity> result = (scopes == null) ? null : new ArrayList<CodegenSecurity>();
598639
if (authMethods != null) {
599640
for (CodegenSecurity authMethod : authMethods) {
600641
if (authMethod.scopes != null) {
@@ -620,8 +661,39 @@ private void postProcessAuthMethod(List<CodegenSecurity> authMethods) {
620661
}
621662
}
622663
}
664+
665+
// If we have operation scopes, filter the auth method to describe the operation auth
666+
// method with only the scope that it requires. We have to create a new auth method
667+
// instance because the original object must not be modified.
668+
List<String> opScopes = (scopes == null) ? null : scopes.get(authMethod.name);
623669
authMethod.name = org.openapitools.codegen.utils.StringUtils.camelize(sanitizeName(authMethod.name), true);
670+
if (opScopes != null) {
671+
CodegenSecurity opSecurity = new CodegenSecurity();
672+
opSecurity.name = authMethod.name;
673+
opSecurity.type = authMethod.type;
674+
opSecurity.hasMore = false;
675+
opSecurity.isBasic = authMethod.isBasic;
676+
opSecurity.isApiKey = authMethod.isApiKey;
677+
opSecurity.isKeyInCookie = authMethod.isKeyInCookie;
678+
opSecurity.isKeyInHeader = authMethod.isKeyInHeader;
679+
opSecurity.isKeyInQuery = authMethod.isKeyInQuery;
680+
opSecurity.flow = authMethod.flow;
681+
opSecurity.tokenUrl = authMethod.tokenUrl;
682+
List<Map<String, Object>> opAuthScopes = new ArrayList<Map<String, Object>>();
683+
for (String opScopeName : opScopes) {
684+
for (Map<String, Object> scope : authMethod.scopes) {
685+
String name = (String) scope.get("scope");
686+
if (opScopeName.equals(name)) {
687+
opAuthScopes.add(scope);
688+
break;
689+
}
690+
}
691+
}
692+
opSecurity.scopes = opAuthScopes;
693+
result.add(opSecurity);
694+
}
624695
}
625696
}
697+
return result;
626698
}
627699
}

modules/openapi-generator/src/main/resources/Ada/server-skeleton-body.mustache

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ package body {{package}}.Skeletons is
1313
package API_{{operationId}} is
1414
new Swagger.Servers.Operation (Handler => {{operationId}},
1515
Method => Swagger.Servers.{{httpMethod}},
16-
URI => "{{path}}");
16+
URI => URI_Prefix & "{{path}}");
1717

1818
-- {{summary}}
1919
procedure {{operationId}}
@@ -32,7 +32,7 @@ package body {{package}}.Skeletons is
3232
Result : {{returnType}};
3333
{{/returnType}}
3434
begin
35-
{{#authMethods}}
35+
{{#vendorExtensions.x-auth-scopes}}
3636
if not Context.Is_Authenticated then
3737
Context.Set_Error (401, "Not authenticated");
3838
return;
@@ -43,7 +43,7 @@ package body {{package}}.Skeletons is
4343
return;
4444
end if;
4545
{{/scopes}}
46-
{{/authMethods}}
46+
{{/vendorExtensions.x-auth-scopes}}
4747
{{#queryParams}}
4848
Swagger.Servers.Get_Query_Parameter (Req, "{{baseName}}", {{paramName}});
4949
{{/queryParams}}
@@ -128,7 +128,7 @@ package body {{package}}.Skeletons is
128128
Result : {{returnType}};
129129
{{/returnType}}
130130
begin
131-
{{#authMethods}}
131+
{{#vendorExtensions.x-auth-scopes}}
132132
if not Context.Is_Authenticated then
133133
Context.Set_Error (401, "Not authenticated");
134134
return;
@@ -139,7 +139,7 @@ package body {{package}}.Skeletons is
139139
return;
140140
end if;
141141
{{/scopes}}
142-
{{/authMethods}}
142+
{{/vendorExtensions.x-auth-scopes}}
143143
{{#queryParams}}
144144
Swagger.Servers.Get_Query_Parameter (Req, "{{baseName}}", {{paramName}});
145145
{{/queryParams}}
@@ -185,7 +185,7 @@ package body {{package}}.Skeletons is
185185
package API_{{operationId}} is
186186
new Swagger.Servers.Operation (Handler => {{operationId}},
187187
Method => Swagger.Servers.{{httpMethod}},
188-
URI => "{{path}}");
188+
URI => URI_Prefix & "{{path}}");
189189
{{/operation}}
190190
{{/operations}}
191191
{{/apis}}

modules/openapi-generator/src/main/resources/Ada/server-skeleton-spec.mustache

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ package {{package}}.Skeletons is
3232

3333
generic
3434
type Implementation_Type is limited new Server_Type with private;
35+
URI_Prefix : String := "";
3536
package Skeleton is
3637

3738
procedure Register (Server : in out Swagger.Servers.Application_Type'Class);
@@ -56,6 +57,7 @@ package {{package}}.Skeletons is
5657

5758
generic
5859
type Implementation_Type is limited new Server_Type with private;
60+
URI_Prefix : String := "";
5961
package Shared_Instance is
6062

6163
procedure Register (Server : in out Swagger.Servers.Application_Type'Class);

0 commit comments

Comments
 (0)