mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-07-04 06:30:52 +00:00
[Core, Rust Server, ASP.NET Core] Fix Codegen Operation Scope Consistency (#3495)
Fix Codegen Operation Scope Consistency - Filter scopes based on operation - Partially revert #1984 to not rely on custom attributes as to whether scopes exist - Fix filtering global authentication schemes
This commit is contained in:
parent
5b4441892f
commit
de162f7f34
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.openapitools.codegen;
|
package org.openapitools.codegen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -38,7 +39,7 @@ public class CodegenSecurity {
|
|||||||
// Oauth specific
|
// Oauth specific
|
||||||
public String flow, authorizationUrl, tokenUrl;
|
public String flow, authorizationUrl, tokenUrl;
|
||||||
public List<Map<String, Object>> scopes;
|
public List<Map<String, Object>> scopes;
|
||||||
public Boolean isCode, isPassword, isApplication, isImplicit, hasScopes;
|
public Boolean isCode, isPassword, isApplication, isImplicit;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -100,4 +101,47 @@ public class CodegenSecurity {
|
|||||||
isImplicit,
|
isImplicit,
|
||||||
scopes);
|
scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return a copy of the security object, filtering out any scopes from the passed-in list.
|
||||||
|
public CodegenSecurity filterByScopeNames(List<String> filterScopes) {
|
||||||
|
CodegenSecurity filteredSecurity = new CodegenSecurity();
|
||||||
|
// Copy all fields except the scopes.
|
||||||
|
filteredSecurity.name = name;
|
||||||
|
filteredSecurity.type = type;
|
||||||
|
filteredSecurity.hasMore = false;
|
||||||
|
filteredSecurity.isBasic = isBasic;
|
||||||
|
filteredSecurity.isBasicBasic = isBasicBasic;
|
||||||
|
filteredSecurity.isBasicBearer = isBasicBearer;
|
||||||
|
filteredSecurity.isApiKey = isApiKey;
|
||||||
|
filteredSecurity.isOAuth = isOAuth;
|
||||||
|
filteredSecurity.keyParamName = keyParamName;
|
||||||
|
filteredSecurity.isCode = isCode;
|
||||||
|
filteredSecurity.isImplicit = isImplicit;
|
||||||
|
filteredSecurity.isApplication = isApplication;
|
||||||
|
filteredSecurity.isPassword = isPassword;
|
||||||
|
filteredSecurity.isKeyInCookie = isKeyInCookie;
|
||||||
|
filteredSecurity.isKeyInHeader = isKeyInHeader;
|
||||||
|
filteredSecurity.isKeyInQuery = isKeyInQuery;
|
||||||
|
filteredSecurity.flow = flow;
|
||||||
|
filteredSecurity.tokenUrl = tokenUrl;
|
||||||
|
filteredSecurity.authorizationUrl = authorizationUrl;
|
||||||
|
// It is not possible to deep copy the extensions, as we have no idea what types they are.
|
||||||
|
// So the filtered method *will* refer to the original extensions, if any.
|
||||||
|
filteredSecurity.vendorExtensions = new HashMap<String, Object>(vendorExtensions);
|
||||||
|
List<Map<String, Object>> returnedScopes = new ArrayList<Map<String, Object>>();
|
||||||
|
Map<String, Object> lastScope = null;
|
||||||
|
for (String filterScopeName : filterScopes) {
|
||||||
|
for (Map<String, Object> scope : scopes) {
|
||||||
|
String name = (String) scope.get("scope");
|
||||||
|
if (filterScopeName.equals(name)) {
|
||||||
|
returnedScopes.add(scope);
|
||||||
|
lastScope = scope;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filteredSecurity.scopes = returnedScopes;
|
||||||
|
|
||||||
|
return filteredSecurity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1057,55 +1057,21 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, SecurityScheme> authMethods = getAuthMethods(securities, securitySchemes);
|
Map<String, SecurityScheme> authMethods = getAuthMethods(securities, securitySchemes);
|
||||||
if (authMethods == null || authMethods.isEmpty()) {
|
|
||||||
authMethods = getAuthMethods(globalSecurities, securitySchemes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authMethods != null && !authMethods.isEmpty()) {
|
if (authMethods != null && !authMethods.isEmpty()) {
|
||||||
codegenOperation.authMethods = config.fromSecurity(authMethods);
|
List<CodegenSecurity> fullAuthMethods = config.fromSecurity(authMethods);
|
||||||
List<Map<String, Object>> scopes = new ArrayList<Map<String, Object>>();
|
codegenOperation.authMethods = filterAuthMethods(fullAuthMethods, securities);
|
||||||
if (codegenOperation.authMethods != null) {
|
codegenOperation.hasAuthMethods = true;
|
||||||
for (CodegenSecurity security : codegenOperation.authMethods) {
|
} else {
|
||||||
if (security != null && security.isBasicBearer != null && security.isBasicBearer &&
|
authMethods = getAuthMethods(globalSecurities, securitySchemes);
|
||||||
securities != null) {
|
|
||||||
for (SecurityRequirement req : securities) {
|
|
||||||
if (req == null) continue;
|
|
||||||
for (String key : req.keySet()) {
|
|
||||||
if (security.name != null && key.equals(security.name)) {
|
|
||||||
int count = 0;
|
|
||||||
for (String sc : req.get(key)) {
|
|
||||||
Map<String, Object> scope = new HashMap<String, Object>();
|
|
||||||
scope.put("scope", sc);
|
|
||||||
scope.put("description", "");
|
|
||||||
count++;
|
|
||||||
if (req.get(key) != null && count < req.get(key).size()) {
|
|
||||||
scope.put("hasMore", "true");
|
|
||||||
} else {
|
|
||||||
scope.put("hasMore", null);
|
|
||||||
}
|
|
||||||
scopes.add(scope);
|
|
||||||
}
|
|
||||||
//end this inner for
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (authMethods != null && !authMethods.isEmpty()) {
|
||||||
security.hasScopes = scopes.size() > 0;
|
List<CodegenSecurity> fullAuthMethods = config.fromSecurity(authMethods);
|
||||||
security.scopes = scopes;
|
codegenOperation.authMethods = filterAuthMethods(fullAuthMethods, globalSecurities);
|
||||||
}
|
codegenOperation.hasAuthMethods = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
codegenOperation.hasAuthMethods = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO need to revise the logic below
|
|
||||||
Map<String, SecurityScheme> securitySchemeMap = openAPI.getComponents().getSecuritySchemes();
|
|
||||||
if (securitySchemeMap != null && !securitySchemeMap.isEmpty()) {
|
|
||||||
codegenOperation.authMethods = config.fromSecurity(securitySchemeMap);
|
|
||||||
codegenOperation.hasAuthMethods = true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
String msg = "Could not process operation:\n" //
|
String msg = "Could not process operation:\n" //
|
||||||
+ " Tag: " + tag + "\n"//
|
+ " Tag: " + tag + "\n"//
|
||||||
@ -1311,6 +1277,40 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
|||||||
.scopes(newScopes);
|
.scopes(newScopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<CodegenSecurity> filterAuthMethods(List<CodegenSecurity> authMethods, List<SecurityRequirement> securities) {
|
||||||
|
if (securities == null || securities.isEmpty() || authMethods == null) {
|
||||||
|
return authMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CodegenSecurity> result = new ArrayList<CodegenSecurity>();
|
||||||
|
|
||||||
|
for (CodegenSecurity security : authMethods) {
|
||||||
|
boolean filtered = false;
|
||||||
|
if (security != null && security.scopes != null) {
|
||||||
|
for (SecurityRequirement requirement : securities) {
|
||||||
|
List<String> opScopes = requirement.get(security.name);
|
||||||
|
if (opScopes != null) {
|
||||||
|
// We have operation-level scopes for this method, so filter the auth method to
|
||||||
|
// describe the operation auth method with only the scopes that it requires.
|
||||||
|
// We have to create a new auth method instance because the original object must
|
||||||
|
// not be modified.
|
||||||
|
CodegenSecurity opSecurity = security.filterByScopeNames(opScopes);
|
||||||
|
result.add(opSecurity);
|
||||||
|
filtered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't get a filtered version, then we can keep the original auth method.
|
||||||
|
if (!filtered) {
|
||||||
|
result.add(security);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasOAuthMethods(List<CodegenSecurity> authMethods) {
|
private boolean hasOAuthMethods(List<CodegenSecurity> authMethods) {
|
||||||
for (CodegenSecurity cs : authMethods) {
|
for (CodegenSecurity cs : authMethods) {
|
||||||
if (Boolean.TRUE.equals(cs.isOAuth)) {
|
if (Boolean.TRUE.equals(cs.isOAuth)) {
|
||||||
|
@ -33,9 +33,15 @@ namespace {{apiPackage}}
|
|||||||
/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}{{#responses}}
|
/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}{{#responses}}
|
||||||
/// <response code="{{code}}">{{message}}</response>{{/responses}}
|
/// <response code="{{code}}">{{message}}</response>{{/responses}}
|
||||||
[{{httpMethod}}]
|
[{{httpMethod}}]
|
||||||
[Route("{{{basePathWithoutHost}}}{{{path}}}")]{{#hasAuthMethods}}{{#authMethods}}{{#isApiKey}}
|
[Route("{{{basePathWithoutHost}}}{{{path}}}")]
|
||||||
[Authorize(Policy = "{{name}}")]{{/isApiKey}}{{#isBasicBearer}}
|
{{#authMethods}}
|
||||||
[Authorize{{#hasScopes}}(Roles = "{{#scopes}}{{scope}}{{#hasMore}},{{/hasMore}}{{/scopes}}"){{/hasScopes}}]{{/isBasicBearer}}{{/authMethods}}{{/hasAuthMethods}}
|
{{#isApiKey}}
|
||||||
|
[Authorize(Policy = "{{name}}")]
|
||||||
|
{{/isApiKey}}
|
||||||
|
{{#isBasicBearer}}
|
||||||
|
[Authorize{{#scopes}}{{#-first}}(Roles = "{{/-first}}{{scope}}{{^-last}},{{/-last}}{{#-last}}"){{/-last}}{{/scopes}}]
|
||||||
|
{{/isBasicBearer}}
|
||||||
|
{{/authMethods}}
|
||||||
[ValidateModelState]{{#useSwashbuckle}}
|
[ValidateModelState]{{#useSwashbuckle}}
|
||||||
[SwaggerOperation("{{operationId}}")]{{#responses}}{{#dataType}}
|
[SwaggerOperation("{{operationId}}")]{{#responses}}{{#dataType}}
|
||||||
[SwaggerResponse(statusCode: {{code}}, type: typeof({{&dataType}}), description: "{{message}}")]{{/dataType}}{{^dataType}}{{/dataType}}{{/responses}}{{/useSwashbuckle}}{{^useSwashbuckle}}{{#responses}}{{#dataType}}
|
[SwaggerResponse(statusCode: {{code}}, type: typeof({{&dataType}}), description: "{{message}}")]{{/dataType}}{{^dataType}}{{/dataType}}{{/responses}}{{/useSwashbuckle}}{{^useSwashbuckle}}{{#responses}}{{#dataType}}
|
||||||
|
@ -101,6 +101,20 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: 'OK'
|
description: 'OK'
|
||||||
|
/readonly_auth_scheme:
|
||||||
|
get:
|
||||||
|
security:
|
||||||
|
- authScheme: ["test.read"]
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Check that limiting to a single required auth scheme works
|
||||||
|
/multiple_auth_scheme:
|
||||||
|
get:
|
||||||
|
security:
|
||||||
|
- authScheme: ["test.read", "test.write"]
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Check that limiting to multiple required auth schemes works
|
||||||
/responses_with_headers:
|
/responses_with_headers:
|
||||||
get:
|
get:
|
||||||
responses:
|
responses:
|
||||||
@ -123,7 +137,18 @@ paths:
|
|||||||
Failure-Info:
|
Failure-Info:
|
||||||
schema:
|
schema:
|
||||||
type: String
|
type: String
|
||||||
|
|
||||||
components:
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
authScheme:
|
||||||
|
type: oauth2
|
||||||
|
flows:
|
||||||
|
authorizationCode:
|
||||||
|
authorizationUrl: 'http://example.org'
|
||||||
|
tokenUrl: 'http://example.org'
|
||||||
|
scopes:
|
||||||
|
test.read: Allowed to read state.
|
||||||
|
test.write: Allowed to change state.
|
||||||
schemas:
|
schemas:
|
||||||
UuidObject:
|
UuidObject:
|
||||||
description: Test a model containing a UUID
|
description: Test a model containing a UUID
|
||||||
|
@ -1 +1 @@
|
|||||||
4.1.1-SNAPSHOT
|
4.1.3-SNAPSHOT
|
File diff suppressed because it is too large
Load Diff
@ -61,6 +61,8 @@ cargo run --example server
|
|||||||
To run a client, follow one of the following simple steps:
|
To run a client, follow one of the following simple steps:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
cargo run --example client MultipleAuthSchemeGet
|
||||||
|
cargo run --example client ReadonlyAuthSchemeGet
|
||||||
cargo run --example client RequiredOctetStreamPut
|
cargo run --example client RequiredOctetStreamPut
|
||||||
cargo run --example client ResponsesWithHeadersGet
|
cargo run --example client ResponsesWithHeadersGet
|
||||||
cargo run --example client UuidGet
|
cargo run --example client UuidGet
|
||||||
@ -102,6 +104,8 @@ All URIs are relative to *http://localhost*
|
|||||||
|
|
||||||
Method | HTTP request | Description
|
Method | HTTP request | Description
|
||||||
------------- | ------------- | -------------
|
------------- | ------------- | -------------
|
||||||
|
[****](docs/default_api.md#) | **GET** /multiple_auth_scheme |
|
||||||
|
[****](docs/default_api.md#) | **GET** /readonly_auth_scheme |
|
||||||
[****](docs/default_api.md#) | **PUT** /required_octet_stream |
|
[****](docs/default_api.md#) | **PUT** /required_octet_stream |
|
||||||
[****](docs/default_api.md#) | **GET** /responses_with_headers |
|
[****](docs/default_api.md#) | **GET** /responses_with_headers |
|
||||||
[****](docs/default_api.md#) | **GET** /uuid |
|
[****](docs/default_api.md#) | **GET** /uuid |
|
||||||
@ -125,8 +129,22 @@ Method | HTTP request | Description
|
|||||||
|
|
||||||
|
|
||||||
## Documentation For Authorization
|
## Documentation For Authorization
|
||||||
Endpoints do not require authorization.
|
|
||||||
|
|
||||||
|
## authScheme
|
||||||
|
- **Type**: OAuth
|
||||||
|
- **Flow**: accessCode
|
||||||
|
- **Authorization URL**: http://example.org
|
||||||
|
- **Scopes**:
|
||||||
|
- **test.read**: Allowed to read state.
|
||||||
|
- **test.write**: Allowed to change state.
|
||||||
|
|
||||||
|
Example
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
Or via OAuth2 module to automatically refresh tokens and perform user authentication.
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
@ -86,6 +86,23 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: OK
|
description: OK
|
||||||
|
/readonly_auth_scheme:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Check that limiting to a single required auth scheme works
|
||||||
|
security:
|
||||||
|
- authScheme:
|
||||||
|
- test.read
|
||||||
|
/multiple_auth_scheme:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Check that limiting to multiple required auth schemes works
|
||||||
|
security:
|
||||||
|
- authScheme:
|
||||||
|
- test.read
|
||||||
|
- test.write
|
||||||
/responses_with_headers:
|
/responses_with_headers:
|
||||||
get:
|
get:
|
||||||
responses:
|
responses:
|
||||||
@ -176,4 +193,14 @@ components:
|
|||||||
xml:
|
xml:
|
||||||
name: snake_another_xml_object
|
name: snake_another_xml_object
|
||||||
namespace: http://foo.bar
|
namespace: http://foo.bar
|
||||||
|
securitySchemes:
|
||||||
|
authScheme:
|
||||||
|
flows:
|
||||||
|
authorizationCode:
|
||||||
|
authorizationUrl: http://example.org
|
||||||
|
scopes:
|
||||||
|
test.read: Allowed to read state.
|
||||||
|
test.write: Allowed to change state.
|
||||||
|
tokenUrl: http://example.org
|
||||||
|
type: oauth2
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ All URIs are relative to *http://localhost*
|
|||||||
|
|
||||||
Method | HTTP request | Description
|
Method | HTTP request | Description
|
||||||
------------- | ------------- | -------------
|
------------- | ------------- | -------------
|
||||||
|
****](default_api.md#) | **GET** /multiple_auth_scheme |
|
||||||
|
****](default_api.md#) | **GET** /readonly_auth_scheme |
|
||||||
****](default_api.md#) | **PUT** /required_octet_stream |
|
****](default_api.md#) | **PUT** /required_octet_stream |
|
||||||
****](default_api.md#) | **GET** /responses_with_headers |
|
****](default_api.md#) | **GET** /responses_with_headers |
|
||||||
****](default_api.md#) | **GET** /uuid |
|
****](default_api.md#) | **GET** /uuid |
|
||||||
@ -14,6 +16,50 @@ Method | HTTP request | Description
|
|||||||
****](default_api.md#) | **PUT** /xml |
|
****](default_api.md#) | **PUT** /xml |
|
||||||
|
|
||||||
|
|
||||||
|
# ****
|
||||||
|
> (ctx, )
|
||||||
|
|
||||||
|
|
||||||
|
### Required Parameters
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
(empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[authScheme](../README.md#authScheme)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: Not defined
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# ****
|
||||||
|
> (ctx, )
|
||||||
|
|
||||||
|
|
||||||
|
### Required Parameters
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
(empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[authScheme](../README.md#authScheme)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: Not defined
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# ****
|
# ****
|
||||||
> (body)
|
> (body)
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ use tokio_core::reactor;
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use openapi_v3::{ApiNoContext, ContextWrapperExt,
|
use openapi_v3::{ApiNoContext, ContextWrapperExt,
|
||||||
ApiError,
|
ApiError,
|
||||||
|
MultipleAuthSchemeGetResponse,
|
||||||
|
ReadonlyAuthSchemeGetResponse,
|
||||||
RequiredOctetStreamPutResponse,
|
RequiredOctetStreamPutResponse,
|
||||||
ResponsesWithHeadersGetResponse,
|
ResponsesWithHeadersGetResponse,
|
||||||
UuidGetResponse,
|
UuidGetResponse,
|
||||||
@ -35,6 +37,8 @@ fn main() {
|
|||||||
.arg(Arg::with_name("operation")
|
.arg(Arg::with_name("operation")
|
||||||
.help("Sets the operation to run")
|
.help("Sets the operation to run")
|
||||||
.possible_values(&[
|
.possible_values(&[
|
||||||
|
"MultipleAuthSchemeGet",
|
||||||
|
"ReadonlyAuthSchemeGet",
|
||||||
"RequiredOctetStreamPut",
|
"RequiredOctetStreamPut",
|
||||||
"ResponsesWithHeadersGet",
|
"ResponsesWithHeadersGet",
|
||||||
"UuidGet",
|
"UuidGet",
|
||||||
@ -83,6 +87,16 @@ fn main() {
|
|||||||
|
|
||||||
match matches.value_of("operation") {
|
match matches.value_of("operation") {
|
||||||
|
|
||||||
|
Some("MultipleAuthSchemeGet") => {
|
||||||
|
let result = core.run(client.multiple_auth_scheme_get());
|
||||||
|
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has<XSpanIdString>).get().clone());
|
||||||
|
},
|
||||||
|
|
||||||
|
Some("ReadonlyAuthSchemeGet") => {
|
||||||
|
let result = core.run(client.readonly_auth_scheme_get());
|
||||||
|
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has<XSpanIdString>).get().clone());
|
||||||
|
},
|
||||||
|
|
||||||
Some("RequiredOctetStreamPut") => {
|
Some("RequiredOctetStreamPut") => {
|
||||||
let result = core.run(client.required_octet_stream_put(swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE"))));
|
let result = core.run(client.required_octet_stream_put(swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE"))));
|
||||||
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has<XSpanIdString>).get().clone());
|
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has<XSpanIdString>).get().clone());
|
||||||
|
@ -13,6 +13,7 @@ use std::marker::PhantomData;
|
|||||||
use hyper;
|
use hyper;
|
||||||
use openapi_v3;
|
use openapi_v3;
|
||||||
use swagger::{Has, XSpanIdString};
|
use swagger::{Has, XSpanIdString};
|
||||||
|
use swagger::auth::Authorization;
|
||||||
|
|
||||||
pub struct NewService<C>{
|
pub struct NewService<C>{
|
||||||
marker: PhantomData<C>
|
marker: PhantomData<C>
|
||||||
@ -24,7 +25,7 @@ impl<C> NewService<C>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Clone + 'static {
|
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Has<Option<Authorization>> + Clone + 'static {
|
||||||
type Request = (hyper::Request, C);
|
type Request = (hyper::Request, C);
|
||||||
type Response = hyper::Response;
|
type Response = hyper::Response;
|
||||||
type Error = hyper::Error;
|
type Error = hyper::Error;
|
||||||
|
@ -11,6 +11,8 @@ use swagger::{Has, XSpanIdString};
|
|||||||
use uuid;
|
use uuid;
|
||||||
|
|
||||||
use openapi_v3::{Api, ApiError,
|
use openapi_v3::{Api, ApiError,
|
||||||
|
MultipleAuthSchemeGetResponse,
|
||||||
|
ReadonlyAuthSchemeGetResponse,
|
||||||
RequiredOctetStreamPutResponse,
|
RequiredOctetStreamPutResponse,
|
||||||
ResponsesWithHeadersGetResponse,
|
ResponsesWithHeadersGetResponse,
|
||||||
UuidGetResponse,
|
UuidGetResponse,
|
||||||
@ -36,6 +38,20 @@ impl<C> Server<C> {
|
|||||||
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
|
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
|
||||||
|
|
||||||
|
|
||||||
|
fn multiple_auth_scheme_get(&self, context: &C) -> Box<Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>> {
|
||||||
|
let context = context.clone();
|
||||||
|
println!("multiple_auth_scheme_get() - X-Span-ID: {:?}", context.get().0.clone());
|
||||||
|
Box::new(futures::failed("Generic failure".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn readonly_auth_scheme_get(&self, context: &C) -> Box<Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>> {
|
||||||
|
let context = context.clone();
|
||||||
|
println!("readonly_auth_scheme_get() - X-Span-ID: {:?}", context.get().0.clone());
|
||||||
|
Box::new(futures::failed("Generic failure".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>> {
|
fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>> {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
println!("required_octet_stream_put({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
|
println!("required_octet_stream_put({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
|
||||||
|
@ -37,6 +37,8 @@ use swagger;
|
|||||||
use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData};
|
use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData};
|
||||||
|
|
||||||
use {Api,
|
use {Api,
|
||||||
|
MultipleAuthSchemeGetResponse,
|
||||||
|
ReadonlyAuthSchemeGetResponse,
|
||||||
RequiredOctetStreamPutResponse,
|
RequiredOctetStreamPutResponse,
|
||||||
ResponsesWithHeadersGetResponse,
|
ResponsesWithHeadersGetResponse,
|
||||||
UuidGetResponse,
|
UuidGetResponse,
|
||||||
@ -248,7 +250,153 @@ impl<F> Client<F> where
|
|||||||
|
|
||||||
impl<F, C> Api<C> for Client<F> where
|
impl<F, C> Api<C> for Client<F> where
|
||||||
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static,
|
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static,
|
||||||
C: Has<XSpanIdString> {
|
C: Has<XSpanIdString> + Has<Option<AuthData>>{
|
||||||
|
|
||||||
|
fn multiple_auth_scheme_get(&self, context: &C) -> Box<Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>> {
|
||||||
|
let mut uri = format!(
|
||||||
|
"{}/multiple_auth_scheme",
|
||||||
|
self.base_path
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
|
||||||
|
|
||||||
|
|
||||||
|
let query_string_str = query_string.finish();
|
||||||
|
if !query_string_str.is_empty() {
|
||||||
|
uri += "?";
|
||||||
|
uri += &query_string_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uri = match Uri::from_str(&uri) {
|
||||||
|
Ok(uri) => uri,
|
||||||
|
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut request = hyper::Request::new(hyper::Method::Get, uri);
|
||||||
|
|
||||||
|
|
||||||
|
request.headers_mut().set(XSpanId((context as &Has<XSpanIdString>).get().0.clone()));
|
||||||
|
|
||||||
|
(context as &Has<Option<AuthData>>).get().as_ref().map(|auth_data| {
|
||||||
|
// Currently only authentication with Basic, API Key, and Bearer are supported
|
||||||
|
match auth_data {
|
||||||
|
&AuthData::Bearer(ref bearer_header) => {
|
||||||
|
request.headers_mut().set(hyper::header::Authorization(
|
||||||
|
bearer_header.clone(),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Box::new(self.client_service.call(request)
|
||||||
|
.map_err(|e| ApiError(format!("No response received: {}", e)))
|
||||||
|
.and_then(|mut response| {
|
||||||
|
match response.status().as_u16() {
|
||||||
|
200 => {
|
||||||
|
let body = response.body();
|
||||||
|
Box::new(
|
||||||
|
|
||||||
|
future::ok(
|
||||||
|
MultipleAuthSchemeGetResponse::CheckThatLimitingToMultipleRequiredAuthSchemesWorks
|
||||||
|
)
|
||||||
|
) as Box<Future<Item=_, Error=_>>
|
||||||
|
},
|
||||||
|
code => {
|
||||||
|
let headers = response.headers().clone();
|
||||||
|
Box::new(response.body()
|
||||||
|
.take(100)
|
||||||
|
.concat2()
|
||||||
|
.then(move |body|
|
||||||
|
future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}",
|
||||||
|
code,
|
||||||
|
headers,
|
||||||
|
match body {
|
||||||
|
Ok(ref body) => match str::from_utf8(body) {
|
||||||
|
Ok(body) => Cow::from(body),
|
||||||
|
Err(e) => Cow::from(format!("<Body was not UTF8: {:?}>", e)),
|
||||||
|
},
|
||||||
|
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
|
||||||
|
})))
|
||||||
|
)
|
||||||
|
) as Box<Future<Item=_, Error=_>>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readonly_auth_scheme_get(&self, context: &C) -> Box<Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>> {
|
||||||
|
let mut uri = format!(
|
||||||
|
"{}/readonly_auth_scheme",
|
||||||
|
self.base_path
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
|
||||||
|
|
||||||
|
|
||||||
|
let query_string_str = query_string.finish();
|
||||||
|
if !query_string_str.is_empty() {
|
||||||
|
uri += "?";
|
||||||
|
uri += &query_string_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uri = match Uri::from_str(&uri) {
|
||||||
|
Ok(uri) => uri,
|
||||||
|
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut request = hyper::Request::new(hyper::Method::Get, uri);
|
||||||
|
|
||||||
|
|
||||||
|
request.headers_mut().set(XSpanId((context as &Has<XSpanIdString>).get().0.clone()));
|
||||||
|
|
||||||
|
(context as &Has<Option<AuthData>>).get().as_ref().map(|auth_data| {
|
||||||
|
// Currently only authentication with Basic, API Key, and Bearer are supported
|
||||||
|
match auth_data {
|
||||||
|
&AuthData::Bearer(ref bearer_header) => {
|
||||||
|
request.headers_mut().set(hyper::header::Authorization(
|
||||||
|
bearer_header.clone(),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Box::new(self.client_service.call(request)
|
||||||
|
.map_err(|e| ApiError(format!("No response received: {}", e)))
|
||||||
|
.and_then(|mut response| {
|
||||||
|
match response.status().as_u16() {
|
||||||
|
200 => {
|
||||||
|
let body = response.body();
|
||||||
|
Box::new(
|
||||||
|
|
||||||
|
future::ok(
|
||||||
|
ReadonlyAuthSchemeGetResponse::CheckThatLimitingToASingleRequiredAuthSchemeWorks
|
||||||
|
)
|
||||||
|
) as Box<Future<Item=_, Error=_>>
|
||||||
|
},
|
||||||
|
code => {
|
||||||
|
let headers = response.headers().clone();
|
||||||
|
Box::new(response.body()
|
||||||
|
.take(100)
|
||||||
|
.concat2()
|
||||||
|
.then(move |body|
|
||||||
|
future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}",
|
||||||
|
code,
|
||||||
|
headers,
|
||||||
|
match body {
|
||||||
|
Ok(ref body) => match str::from_utf8(body) {
|
||||||
|
Ok(body) => Cow::from(body),
|
||||||
|
Err(e) => Cow::from(format!("<Body was not UTF8: {:?}>", e)),
|
||||||
|
},
|
||||||
|
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
|
||||||
|
})))
|
||||||
|
)
|
||||||
|
) as Box<Future<Item=_, Error=_>>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn required_octet_stream_put(&self, param_body: swagger::ByteArray, context: &C) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>> {
|
fn required_octet_stream_put(&self, param_body: swagger::ByteArray, context: &C) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>> {
|
||||||
let mut uri = format!(
|
let mut uri = format!(
|
||||||
@ -272,7 +420,6 @@ impl<F, C> Api<C> for Client<F> where
|
|||||||
|
|
||||||
let mut request = hyper::Request::new(hyper::Method::Put, uri);
|
let mut request = hyper::Request::new(hyper::Method::Put, uri);
|
||||||
|
|
||||||
// Body parameter
|
|
||||||
let body = param_body.0;
|
let body = param_body.0;
|
||||||
request.set_body(body);
|
request.set_body(body);
|
||||||
|
|
||||||
|
@ -51,6 +51,18 @@ pub const BASE_PATH: &'static str = "";
|
|||||||
pub const API_VERSION: &'static str = "1.0.7";
|
pub const API_VERSION: &'static str = "1.0.7";
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum MultipleAuthSchemeGetResponse {
|
||||||
|
/// Check that limiting to multiple required auth schemes works
|
||||||
|
CheckThatLimitingToMultipleRequiredAuthSchemesWorks
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum ReadonlyAuthSchemeGetResponse {
|
||||||
|
/// Check that limiting to a single required auth scheme works
|
||||||
|
CheckThatLimitingToASingleRequiredAuthSchemeWorks
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum RequiredOctetStreamPutResponse {
|
pub enum RequiredOctetStreamPutResponse {
|
||||||
/// OK
|
/// OK
|
||||||
@ -131,6 +143,12 @@ pub enum XmlPutResponse {
|
|||||||
pub trait Api<C> {
|
pub trait Api<C> {
|
||||||
|
|
||||||
|
|
||||||
|
fn multiple_auth_scheme_get(&self, context: &C) -> Box<Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>>;
|
||||||
|
|
||||||
|
|
||||||
|
fn readonly_auth_scheme_get(&self, context: &C) -> Box<Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>>;
|
||||||
|
|
||||||
|
|
||||||
fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>>;
|
fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>>;
|
||||||
|
|
||||||
|
|
||||||
@ -160,6 +178,12 @@ pub trait Api<C> {
|
|||||||
pub trait ApiNoContext {
|
pub trait ApiNoContext {
|
||||||
|
|
||||||
|
|
||||||
|
fn multiple_auth_scheme_get(&self) -> Box<Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>>;
|
||||||
|
|
||||||
|
|
||||||
|
fn readonly_auth_scheme_get(&self) -> Box<Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>>;
|
||||||
|
|
||||||
|
|
||||||
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>>;
|
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>>;
|
||||||
|
|
||||||
|
|
||||||
@ -200,6 +224,16 @@ impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
|
|||||||
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
|
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
|
||||||
|
|
||||||
|
|
||||||
|
fn multiple_auth_scheme_get(&self) -> Box<Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>> {
|
||||||
|
self.api().multiple_auth_scheme_get(&self.context())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn readonly_auth_scheme_get(&self) -> Box<Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>> {
|
||||||
|
self.api().readonly_auth_scheme_get(&self.context())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>> {
|
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>> {
|
||||||
self.api().required_octet_stream_put(body, &self.context())
|
self.api().required_octet_stream_put(body, &self.context())
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,16 @@ impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
|
|||||||
fn call(&self, req: Self::Request) -> Self::Future {
|
fn call(&self, req: Self::Request) -> Self::Future {
|
||||||
let context = A::default().push(XSpanIdString::get_or_generate(&req));
|
let context = A::default().push(XSpanIdString::get_or_generate(&req));
|
||||||
|
|
||||||
|
{
|
||||||
|
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
|
||||||
|
use std::ops::Deref;
|
||||||
|
if let Some(bearer) = req.headers().get::<HyperAuth<Bearer>>().cloned() {
|
||||||
|
let auth_data = AuthData::Bearer(bearer.deref().clone());
|
||||||
|
let context = context.push(Some(auth_data));
|
||||||
|
let context = context.push(None::<Authorization>);
|
||||||
|
return self.inner.call((req, context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let context = context.push(None::<AuthData>);
|
let context = context.push(None::<AuthData>);
|
||||||
let context = context.push(None::<Authorization>);
|
let context = context.push(None::<Authorization>);
|
||||||
|
@ -35,6 +35,8 @@ use swagger::{ApiError, XSpanId, XSpanIdString, Has, RequestParser};
|
|||||||
use swagger::auth::Scopes;
|
use swagger::auth::Scopes;
|
||||||
|
|
||||||
use {Api,
|
use {Api,
|
||||||
|
MultipleAuthSchemeGetResponse,
|
||||||
|
ReadonlyAuthSchemeGetResponse,
|
||||||
RequiredOctetStreamPutResponse,
|
RequiredOctetStreamPutResponse,
|
||||||
ResponsesWithHeadersGetResponse,
|
ResponsesWithHeadersGetResponse,
|
||||||
UuidGetResponse,
|
UuidGetResponse,
|
||||||
@ -56,6 +58,8 @@ mod paths {
|
|||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(vec![
|
pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(vec![
|
||||||
|
r"^/multiple_auth_scheme$",
|
||||||
|
r"^/readonly_auth_scheme$",
|
||||||
r"^/required_octet_stream$",
|
r"^/required_octet_stream$",
|
||||||
r"^/responses_with_headers$",
|
r"^/responses_with_headers$",
|
||||||
r"^/uuid$",
|
r"^/uuid$",
|
||||||
@ -64,12 +68,14 @@ mod paths {
|
|||||||
r"^/xml_other$"
|
r"^/xml_other$"
|
||||||
]).unwrap();
|
]).unwrap();
|
||||||
}
|
}
|
||||||
pub static ID_REQUIRED_OCTET_STREAM: usize = 0;
|
pub static ID_MULTIPLE_AUTH_SCHEME: usize = 0;
|
||||||
pub static ID_RESPONSES_WITH_HEADERS: usize = 1;
|
pub static ID_READONLY_AUTH_SCHEME: usize = 1;
|
||||||
pub static ID_UUID: usize = 2;
|
pub static ID_REQUIRED_OCTET_STREAM: usize = 2;
|
||||||
pub static ID_XML: usize = 3;
|
pub static ID_RESPONSES_WITH_HEADERS: usize = 3;
|
||||||
pub static ID_XML_EXTRA: usize = 4;
|
pub static ID_UUID: usize = 4;
|
||||||
pub static ID_XML_OTHER: usize = 5;
|
pub static ID_XML: usize = 5;
|
||||||
|
pub static ID_XML_EXTRA: usize = 6;
|
||||||
|
pub static ID_XML_OTHER: usize = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NewService<T, C> {
|
pub struct NewService<T, C> {
|
||||||
@ -80,7 +86,7 @@ pub struct NewService<T, C> {
|
|||||||
impl<T, C> NewService<T, C>
|
impl<T, C> NewService<T, C>
|
||||||
where
|
where
|
||||||
T: Api<C> + Clone + 'static,
|
T: Api<C> + Clone + 'static,
|
||||||
C: Has<XSpanIdString> + 'static
|
C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static
|
||||||
{
|
{
|
||||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
|
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
|
||||||
NewService{api_impl: api_impl.into(), marker: PhantomData}
|
NewService{api_impl: api_impl.into(), marker: PhantomData}
|
||||||
@ -90,7 +96,7 @@ where
|
|||||||
impl<T, C> hyper::server::NewService for NewService<T, C>
|
impl<T, C> hyper::server::NewService for NewService<T, C>
|
||||||
where
|
where
|
||||||
T: Api<C> + Clone + 'static,
|
T: Api<C> + Clone + 'static,
|
||||||
C: Has<XSpanIdString> + 'static
|
C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static
|
||||||
{
|
{
|
||||||
type Request = (Request, C);
|
type Request = (Request, C);
|
||||||
type Response = Response;
|
type Response = Response;
|
||||||
@ -110,7 +116,7 @@ pub struct Service<T, C> {
|
|||||||
impl<T, C> Service<T, C>
|
impl<T, C> Service<T, C>
|
||||||
where
|
where
|
||||||
T: Api<C> + Clone + 'static,
|
T: Api<C> + Clone + 'static,
|
||||||
C: Has<XSpanIdString> + 'static {
|
C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static {
|
||||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
|
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
|
||||||
Service{api_impl: api_impl.into(), marker: PhantomData}
|
Service{api_impl: api_impl.into(), marker: PhantomData}
|
||||||
}
|
}
|
||||||
@ -119,7 +125,7 @@ where
|
|||||||
impl<T, C> hyper::server::Service for Service<T, C>
|
impl<T, C> hyper::server::Service for Service<T, C>
|
||||||
where
|
where
|
||||||
T: Api<C> + Clone + 'static,
|
T: Api<C> + Clone + 'static,
|
||||||
C: Has<XSpanIdString> + 'static
|
C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static
|
||||||
{
|
{
|
||||||
type Request = (Request, C);
|
type Request = (Request, C);
|
||||||
type Response = Response;
|
type Response = Response;
|
||||||
@ -135,6 +141,127 @@ where
|
|||||||
// Please update both places if changing how this code is autogenerated.
|
// Please update both places if changing how this code is autogenerated.
|
||||||
match &method {
|
match &method {
|
||||||
|
|
||||||
|
// MultipleAuthSchemeGet - GET /multiple_auth_scheme
|
||||||
|
&hyper::Method::Get if path.matched(paths::ID_MULTIPLE_AUTH_SCHEME) => {
|
||||||
|
{
|
||||||
|
let authorization = match (&context as &Has<Option<Authorization>>).get() {
|
||||||
|
&Some(ref authorization) => authorization,
|
||||||
|
&None => return Box::new(future::ok(Response::new()
|
||||||
|
.with_status(StatusCode::Forbidden)
|
||||||
|
.with_body("Unauthenticated"))),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Authorization
|
||||||
|
if let Scopes::Some(ref scopes) = authorization.scopes {
|
||||||
|
let required_scopes: BTreeSet<String> = vec![
|
||||||
|
"test.read".to_string(), // Allowed to read state.
|
||||||
|
"test.write".to_string(), // Allowed to change state.
|
||||||
|
].into_iter().collect();
|
||||||
|
|
||||||
|
if !required_scopes.is_subset(scopes) {
|
||||||
|
let missing_scopes = required_scopes.difference(scopes);
|
||||||
|
return Box::new(future::ok(Response::new()
|
||||||
|
.with_status(StatusCode::Forbidden)
|
||||||
|
.with_body(missing_scopes.fold(
|
||||||
|
"Insufficient authorization, missing scopes".to_string(),
|
||||||
|
|s, scope| format!("{} {}", s, scope)
|
||||||
|
))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Box::new({
|
||||||
|
{{
|
||||||
|
Box::new(api_impl.multiple_auth_scheme_get(&context)
|
||||||
|
.then(move |result| {
|
||||||
|
let mut response = Response::new();
|
||||||
|
response.headers_mut().set(XSpanId((&context as &Has<XSpanIdString>).get().0.to_string()));
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(rsp) => match rsp {
|
||||||
|
MultipleAuthSchemeGetResponse::CheckThatLimitingToMultipleRequiredAuthSchemesWorks
|
||||||
|
|
||||||
|
|
||||||
|
=> {
|
||||||
|
response.set_status(StatusCode::try_from(200).unwrap());
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// Application code returned an error. This should not happen, as the implementation should
|
||||||
|
// return a valid response.
|
||||||
|
response.set_status(StatusCode::InternalServerError);
|
||||||
|
response.set_body("An internal error occurred");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
future::ok(response)
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}}
|
||||||
|
}) as Box<Future<Item=Response, Error=Error>>
|
||||||
|
},
|
||||||
|
|
||||||
|
// ReadonlyAuthSchemeGet - GET /readonly_auth_scheme
|
||||||
|
&hyper::Method::Get if path.matched(paths::ID_READONLY_AUTH_SCHEME) => {
|
||||||
|
{
|
||||||
|
let authorization = match (&context as &Has<Option<Authorization>>).get() {
|
||||||
|
&Some(ref authorization) => authorization,
|
||||||
|
&None => return Box::new(future::ok(Response::new()
|
||||||
|
.with_status(StatusCode::Forbidden)
|
||||||
|
.with_body("Unauthenticated"))),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Authorization
|
||||||
|
if let Scopes::Some(ref scopes) = authorization.scopes {
|
||||||
|
let required_scopes: BTreeSet<String> = vec![
|
||||||
|
"test.read".to_string(), // Allowed to read state.
|
||||||
|
].into_iter().collect();
|
||||||
|
|
||||||
|
if !required_scopes.is_subset(scopes) {
|
||||||
|
let missing_scopes = required_scopes.difference(scopes);
|
||||||
|
return Box::new(future::ok(Response::new()
|
||||||
|
.with_status(StatusCode::Forbidden)
|
||||||
|
.with_body(missing_scopes.fold(
|
||||||
|
"Insufficient authorization, missing scopes".to_string(),
|
||||||
|
|s, scope| format!("{} {}", s, scope)
|
||||||
|
))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Box::new({
|
||||||
|
{{
|
||||||
|
Box::new(api_impl.readonly_auth_scheme_get(&context)
|
||||||
|
.then(move |result| {
|
||||||
|
let mut response = Response::new();
|
||||||
|
response.headers_mut().set(XSpanId((&context as &Has<XSpanIdString>).get().0.to_string()));
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(rsp) => match rsp {
|
||||||
|
ReadonlyAuthSchemeGetResponse::CheckThatLimitingToASingleRequiredAuthSchemeWorks
|
||||||
|
|
||||||
|
|
||||||
|
=> {
|
||||||
|
response.set_status(StatusCode::try_from(200).unwrap());
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// Application code returned an error. This should not happen, as the implementation should
|
||||||
|
// return a valid response.
|
||||||
|
response.set_status(StatusCode::InternalServerError);
|
||||||
|
response.set_body("An internal error occurred");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
future::ok(response)
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}}
|
||||||
|
}) as Box<Future<Item=Response, Error=Error>>
|
||||||
|
},
|
||||||
|
|
||||||
// RequiredOctetStreamPut - PUT /required_octet_stream
|
// RequiredOctetStreamPut - PUT /required_octet_stream
|
||||||
&hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => {
|
&hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => {
|
||||||
// Body parameters (note that non-required body parameters will ignore garbage
|
// Body parameters (note that non-required body parameters will ignore garbage
|
||||||
@ -644,6 +771,12 @@ impl RequestParser for ApiRequestParser {
|
|||||||
let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
|
let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
|
||||||
match request.method() {
|
match request.method() {
|
||||||
|
|
||||||
|
// MultipleAuthSchemeGet - GET /multiple_auth_scheme
|
||||||
|
&hyper::Method::Get if path.matched(paths::ID_MULTIPLE_AUTH_SCHEME) => Ok("MultipleAuthSchemeGet"),
|
||||||
|
|
||||||
|
// ReadonlyAuthSchemeGet - GET /readonly_auth_scheme
|
||||||
|
&hyper::Method::Get if path.matched(paths::ID_READONLY_AUTH_SCHEME) => Ok("ReadonlyAuthSchemeGet"),
|
||||||
|
|
||||||
// RequiredOctetStreamPut - PUT /required_octet_stream
|
// RequiredOctetStreamPut - PUT /required_octet_stream
|
||||||
&hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => Ok("RequiredOctetStreamPut"),
|
&hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => Ok("RequiredOctetStreamPut"),
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user