forked from loafle/openapi-generator-original
[Rust-Axum] Support Authentication (Cookie, API Key In Header) (#20017)
* [Rust-Axum] Support Cookie Authentication & API Key In Header * Fix * Fix * Fix Header Params & Responses
This commit is contained in:
parent
06547b7b82
commit
cded99c3fc
11
bin/configs/manual/rust-axum-apikey-auths.yaml
Normal file
11
bin/configs/manual/rust-axum-apikey-auths.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
generatorName: rust-axum
|
||||||
|
outputDir: samples/server/petstore/rust-axum/output/apikey-auths
|
||||||
|
inputSpec: modules/openapi-generator/src/test/resources/3_0/jetbrains/CheckoutBasicBearerCookieQueryHeaderBasicBearer.yaml
|
||||||
|
templateDir: modules/openapi-generator/src/main/resources/rust-axum
|
||||||
|
generateAliasAsModel: true
|
||||||
|
additionalProperties:
|
||||||
|
hideGenerationTimestamp: "true"
|
||||||
|
packageName: apikey-auths
|
||||||
|
globalProperties:
|
||||||
|
skipFormModel: false
|
||||||
|
enablePostProcessFile: true
|
@ -198,7 +198,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
|||||||
|Body|✓|OAS2
|
|Body|✓|OAS2
|
||||||
|FormUnencoded|✓|OAS2
|
|FormUnencoded|✓|OAS2
|
||||||
|FormMultipart|✓|OAS2
|
|FormMultipart|✓|OAS2
|
||||||
|Cookie|✗|OAS3
|
|Cookie|✓|OAS3
|
||||||
|
|
||||||
### Schema Support Feature
|
### Schema Support Feature
|
||||||
| Name | Supported | Defined By |
|
| Name | Supported | Defined By |
|
||||||
@ -215,14 +215,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
|||||||
### Security Feature
|
### Security Feature
|
||||||
| Name | Supported | Defined By |
|
| Name | Supported | Defined By |
|
||||||
| ---- | --------- | ---------- |
|
| ---- | --------- | ---------- |
|
||||||
|BasicAuth|✓|OAS2,OAS3
|
|BasicAuth|✗|OAS2,OAS3
|
||||||
|ApiKey|✓|OAS2,OAS3
|
|ApiKey|✓|OAS2,OAS3
|
||||||
|OpenIDConnect|✗|OAS3
|
|OpenIDConnect|✗|OAS3
|
||||||
|BearerToken|✓|OAS3
|
|BearerToken|✗|OAS3
|
||||||
|OAuth2_Implicit|✓|OAS2,OAS3
|
|OAuth2_Implicit|✗|OAS2,OAS3
|
||||||
|OAuth2_Password|✓|OAS2,OAS3
|
|OAuth2_Password|✗|OAS2,OAS3
|
||||||
|OAuth2_ClientCredentials|✓|OAS2,OAS3
|
|OAuth2_ClientCredentials|✗|OAS2,OAS3
|
||||||
|OAuth2_AuthorizationCode|✓|OAS2,OAS3
|
|OAuth2_AuthorizationCode|✗|OAS2,OAS3
|
||||||
|SignatureAuth|✗|OAS3
|
|SignatureAuth|✗|OAS3
|
||||||
|AWSV4Signature|✗|ToolingExtension
|
|AWSV4Signature|✗|ToolingExtension
|
||||||
|
|
||||||
|
@ -25,15 +25,13 @@ import io.swagger.v3.oas.models.parameters.Parameter;
|
|||||||
import io.swagger.v3.oas.models.parameters.RequestBody;
|
import io.swagger.v3.oas.models.parameters.RequestBody;
|
||||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||||
import io.swagger.v3.oas.models.servers.Server;
|
import io.swagger.v3.oas.models.servers.Server;
|
||||||
|
import io.swagger.v3.oas.models.tags.Tag;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openapitools.codegen.*;
|
import org.openapitools.codegen.*;
|
||||||
import org.openapitools.codegen.meta.GeneratorMetadata;
|
import org.openapitools.codegen.meta.GeneratorMetadata;
|
||||||
import org.openapitools.codegen.meta.Stability;
|
import org.openapitools.codegen.meta.Stability;
|
||||||
import org.openapitools.codegen.meta.features.GlobalFeature;
|
import org.openapitools.codegen.meta.features.*;
|
||||||
import org.openapitools.codegen.meta.features.ParameterFeature;
|
|
||||||
import org.openapitools.codegen.meta.features.SchemaSupportFeature;
|
|
||||||
import org.openapitools.codegen.meta.features.WireFormatFeature;
|
|
||||||
import org.openapitools.codegen.model.ModelMap;
|
import org.openapitools.codegen.model.ModelMap;
|
||||||
import org.openapitools.codegen.model.ModelsMap;
|
import org.openapitools.codegen.model.ModelsMap;
|
||||||
import org.openapitools.codegen.model.OperationMap;
|
import org.openapitools.codegen.model.OperationMap;
|
||||||
@ -53,7 +51,6 @@ import static org.openapitools.codegen.utils.StringUtils.underscore;
|
|||||||
|
|
||||||
public class RustAxumServerCodegen extends AbstractRustCodegen implements CodegenConfig {
|
public class RustAxumServerCodegen extends AbstractRustCodegen implements CodegenConfig {
|
||||||
public static final String PROJECT_NAME = "openapi-server";
|
public static final String PROJECT_NAME = "openapi-server";
|
||||||
private static final String apiPath = "rust-axum";
|
|
||||||
|
|
||||||
private String packageName;
|
private String packageName;
|
||||||
private String packageVersion;
|
private String packageVersion;
|
||||||
@ -99,6 +96,9 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
WireFormatFeature.JSON,
|
WireFormatFeature.JSON,
|
||||||
WireFormatFeature.Custom
|
WireFormatFeature.Custom
|
||||||
))
|
))
|
||||||
|
.securityFeatures(EnumSet.of(
|
||||||
|
SecurityFeature.ApiKey
|
||||||
|
))
|
||||||
.excludeGlobalFeatures(
|
.excludeGlobalFeatures(
|
||||||
GlobalFeature.Info,
|
GlobalFeature.Info,
|
||||||
GlobalFeature.ExternalDocumentation,
|
GlobalFeature.ExternalDocumentation,
|
||||||
@ -113,9 +113,6 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
.excludeSchemaSupportFeatures(
|
.excludeSchemaSupportFeatures(
|
||||||
SchemaSupportFeature.Polymorphism
|
SchemaSupportFeature.Polymorphism
|
||||||
)
|
)
|
||||||
.excludeParameterFeatures(
|
|
||||||
ParameterFeature.Cookie
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
|
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
|
||||||
@ -436,7 +433,10 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
}
|
}
|
||||||
pathMethodOpMap
|
pathMethodOpMap
|
||||||
.computeIfAbsent(axumPath, (key) -> new ArrayList<>())
|
.computeIfAbsent(axumPath, (key) -> new ArrayList<>())
|
||||||
.add(new MethodOperation(op.httpMethod.toLowerCase(Locale.ROOT), underscoredOperationId));
|
.add(new MethodOperation(
|
||||||
|
op.httpMethod.toLowerCase(Locale.ROOT),
|
||||||
|
underscoredOperationId,
|
||||||
|
op.vendorExtensions));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the types that this operation produces. `getProducesInfo`
|
// Determine the types that this operation produces. `getProducesInfo`
|
||||||
@ -488,7 +488,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
);
|
);
|
||||||
rsp.vendorExtensions.put("x-response-id", responseId);
|
rsp.vendorExtensions.put("x-response-id", responseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsp.dataType != null) {
|
if (rsp.dataType != null) {
|
||||||
// Get the mimetype which is produced by this response. Note
|
// Get the mimetype which is produced by this response. Note
|
||||||
// that although in general responses produces a set of
|
// that although in general responses produces a set of
|
||||||
@ -562,19 +562,39 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (CodegenProperty header : rsp.headers) {
|
||||||
|
if (uuidType.equals(header.dataType)) {
|
||||||
|
additionalProperties.put("apiUsesUuid", true);
|
||||||
|
}
|
||||||
|
header.nameInPascalCase = toModelName(header.baseName);
|
||||||
|
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include renderUuidConversionImpl exactly once in the vendorExtensions map when
|
for (CodegenParameter header : op.headerParams) {
|
||||||
// at least one `uuid::Uuid` converted from a header value in the resulting Rust code.
|
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
|
||||||
final Boolean renderUuidConversionImpl = op.headerParams.stream().anyMatch(h -> h.getDataType().equals(uuidType));
|
}
|
||||||
if (renderUuidConversionImpl) {
|
|
||||||
|
for (CodegenProperty header : op.responseHeaders) {
|
||||||
|
if (uuidType.equals(header.dataType)) {
|
||||||
|
additionalProperties.put("apiUsesUuid", true);
|
||||||
|
}
|
||||||
|
header.nameInPascalCase = toModelName(header.baseName);
|
||||||
|
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include renderUuidConversionImpl exactly once in the vendorExtensions map when
|
||||||
|
// at least one `uuid::Uuid` converted from a header value in the resulting Rust code.
|
||||||
|
final boolean renderUuidConversionImpl = op.headerParams.stream().anyMatch(h -> h.getDataType().equals(uuidType));
|
||||||
|
if (renderUuidConversionImpl)
|
||||||
additionalProperties.put("renderUuidConversionImpl", "true");
|
additionalProperties.put("renderUuidConversionImpl", "true");
|
||||||
}
|
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OperationsMap postProcessOperationsWithModels(OperationsMap operationsMap, List<ModelMap> allModels) {
|
public OperationsMap postProcessOperationsWithModels(final OperationsMap operationsMap, List<ModelMap> allModels) {
|
||||||
OperationMap operations = operationsMap.getOperations();
|
OperationMap operations = operationsMap.getOperations();
|
||||||
operations.put("classnamePascalCase", camelize(operations.getClassname()));
|
operations.put("classnamePascalCase", camelize(operations.getClassname()));
|
||||||
List<CodegenOperation> operationList = operations.getOperation();
|
List<CodegenOperation> operationList = operations.getOperation();
|
||||||
@ -586,7 +606,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
return operationsMap;
|
return operationsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postProcessOperationWithModels(CodegenOperation op) {
|
private void postProcessOperationWithModels(final CodegenOperation op) {
|
||||||
boolean consumesJson = false;
|
boolean consumesJson = false;
|
||||||
boolean consumesPlainText = false;
|
boolean consumesPlainText = false;
|
||||||
boolean consumesFormUrlEncoded = false;
|
boolean consumesFormUrlEncoded = false;
|
||||||
@ -641,6 +661,22 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
param.vendorExtensions.put("x-consumes-json", true);
|
param.vendorExtensions.put("x-consumes-json", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op.authMethods != null) {
|
||||||
|
for (CodegenSecurity s : op.authMethods) {
|
||||||
|
if (s.isApiKey && (s.isKeyInCookie || s.isKeyInHeader)) {
|
||||||
|
if (s.isKeyInCookie) {
|
||||||
|
op.vendorExtensions.put("x-has-cookie-auth-methods", "true");
|
||||||
|
op.vendorExtensions.put("x-api-key-cookie-name", toModelName(s.keyParamName));
|
||||||
|
} else {
|
||||||
|
op.vendorExtensions.put("x-has-header-auth-methods", "true");
|
||||||
|
op.vendorExtensions.put("x-api-key-header-name", toModelName(s.keyParamName));
|
||||||
|
}
|
||||||
|
|
||||||
|
op.vendorExtensions.put("x-has-auth-methods", "true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -671,14 +707,16 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all tags sorted by name
|
// Get all tags sorted by name & Combine into a single group
|
||||||
final List<String> tags = op.tags.stream().map(t -> t.getName()).sorted().collect(Collectors.toList());
|
final String combinedTag = op.tags.stream()
|
||||||
// Combine into a single group
|
.map(Tag::getName).sorted()
|
||||||
final String combinedTag = tags.stream().collect(Collectors.joining("-"));
|
.collect(Collectors.joining("-"));
|
||||||
// Add to group
|
// Add to group
|
||||||
super.addOperationToGroup(combinedTag, resourcePath, operation, op, operations);
|
super.addOperationToGroup(combinedTag, resourcePath, operation, op, operations);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.addOperationToGroup(tag, resourcePath, operation, op, operations);
|
super.addOperationToGroup(tag, resourcePath, operation, op, operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,7 +730,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
// restore things to sensible values.
|
// restore things to sensible values.
|
||||||
@Override
|
@Override
|
||||||
public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, String bodyParameterName) {
|
public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, String bodyParameterName) {
|
||||||
Schema original_schema = ModelUtils.getSchemaFromRequestBody(body);
|
final Schema original_schema = ModelUtils.getSchemaFromRequestBody(body);
|
||||||
CodegenParameter codegenParameter = super.fromRequestBody(body, imports, bodyParameterName);
|
CodegenParameter codegenParameter = super.fromRequestBody(body, imports, bodyParameterName);
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(original_schema.get$ref())) {
|
if (StringUtils.isNotBlank(original_schema.get$ref())) {
|
||||||
@ -709,12 +747,12 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toInstantiationType(Schema p) {
|
public String toInstantiationType(final Schema p) {
|
||||||
if (ModelUtils.isArraySchema(p)) {
|
if (ModelUtils.isArraySchema(p)) {
|
||||||
Schema inner = ModelUtils.getSchemaItems(p);
|
final Schema inner = ModelUtils.getSchemaItems(p);
|
||||||
return instantiationTypes.get("array") + "<" + getSchemaType(inner) + ">";
|
return instantiationTypes.get("array") + "<" + getSchemaType(inner) + ">";
|
||||||
} else if (ModelUtils.isMapSchema(p)) {
|
} else if (ModelUtils.isMapSchema(p)) {
|
||||||
Schema inner = ModelUtils.getAdditionalProperties(p);
|
final Schema inner = ModelUtils.getAdditionalProperties(p);
|
||||||
return instantiationTypes.get("map") + "<" + typeMapping.get("string") + ", " + getSchemaType(inner) + ">";
|
return instantiationTypes.get("map") + "<" + typeMapping.get("string") + ", " + getSchemaType(inner) + ">";
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -727,7 +765,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
|
|
||||||
final List<PathMethodOperations> pathMethodOps = pathMethodOpMap.entrySet().stream()
|
final List<PathMethodOperations> pathMethodOps = pathMethodOpMap.entrySet().stream()
|
||||||
.map(entry -> {
|
.map(entry -> {
|
||||||
ArrayList<MethodOperation> methodOps = entry.getValue();
|
final ArrayList<MethodOperation> methodOps = entry.getValue();
|
||||||
methodOps.sort(Comparator.comparing(a -> a.method));
|
methodOps.sort(Comparator.comparing(a -> a.method));
|
||||||
return new PathMethodOperations(entry.getKey(), methodOps);
|
return new PathMethodOperations(entry.getKey(), methodOps);
|
||||||
})
|
})
|
||||||
@ -739,7 +777,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toDefaultValue(Schema p) {
|
public String toDefaultValue(final Schema p) {
|
||||||
String defaultValue = null;
|
String defaultValue = null;
|
||||||
if ((ModelUtils.isNullable(p)) && (p.getDefault() != null) && ("null".equalsIgnoreCase(p.getDefault().toString())))
|
if ((ModelUtils.isNullable(p)) && (p.getDefault() != null) && ("null".equalsIgnoreCase(p.getDefault().toString())))
|
||||||
return "Nullable::Null";
|
return "Nullable::Null";
|
||||||
@ -899,7 +937,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updatePropertyForAnyType(CodegenProperty property, Schema p) {
|
protected void updatePropertyForAnyType(final CodegenProperty property, final Schema p) {
|
||||||
// The 'null' value is allowed when the OAS schema is 'any type'.
|
// The 'null' value is allowed when the OAS schema is 'any type'.
|
||||||
// See https://github.com/OAI/OpenAPI-Specification/issues/1389
|
// See https://github.com/OAI/OpenAPI-Specification/issues/1389
|
||||||
if (Boolean.FALSE.equals(p.getNullable())) {
|
if (Boolean.FALSE.equals(p.getNullable())) {
|
||||||
@ -917,7 +955,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getParameterDataType(Parameter parameter, Schema schema) {
|
protected String getParameterDataType(final Parameter parameter, final Schema schema) {
|
||||||
if (parameter.get$ref() != null) {
|
if (parameter.get$ref() != null) {
|
||||||
String refName = ModelUtils.getSimpleRef(parameter.get$ref());
|
String refName = ModelUtils.getSimpleRef(parameter.get$ref());
|
||||||
return toModelName(refName);
|
return toModelName(refName);
|
||||||
@ -938,10 +976,12 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
|||||||
static class MethodOperation {
|
static class MethodOperation {
|
||||||
public String method;
|
public String method;
|
||||||
public String operationID;
|
public String operationID;
|
||||||
|
public Map<String, Object> vendorExtensions;
|
||||||
|
|
||||||
MethodOperation(String method, String operationID) {
|
MethodOperation(String method, String operationID, Map<String, Object> vendorExtensions) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.operationID = operationID;
|
this.operationID = operationID;
|
||||||
|
this.vendorExtensions = vendorExtensions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,3 +4,19 @@ pub mod {{classFilename}};
|
|||||||
{{/apis}}
|
{{/apis}}
|
||||||
{{/apiInfo}}
|
{{/apiInfo}}
|
||||||
|
|
||||||
|
{{#authMethods}}
|
||||||
|
{{#isApiKey}}
|
||||||
|
{{#isKeyInCookie}}
|
||||||
|
/// Cookie Authentication.
|
||||||
|
pub trait CookieAuthentication {
|
||||||
|
fn extract_token_from_cookie(&self, cookies: &axum_extra::extract::CookieJar, key: &str) -> Option<String>;
|
||||||
|
}
|
||||||
|
{{/isKeyInCookie}}
|
||||||
|
{{#isKeyInHeader}}
|
||||||
|
/// API Key Authentication - Header.
|
||||||
|
pub trait ApiKeyAuthHeader {
|
||||||
|
fn extract_token_from_header(&self, headers: &axum::http::header::HeaderMap, key: &str) -> Option<String>;
|
||||||
|
}
|
||||||
|
{{/isKeyInHeader}}
|
||||||
|
{{/isApiKey}}
|
||||||
|
{{/authMethods}}
|
@ -30,6 +30,14 @@ pub trait {{classnamePascalCase}} {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
{{#vendorExtensions}}
|
||||||
|
{{#x-has-cookie-auth-methods}}
|
||||||
|
token_in_cookie: Option<String>,
|
||||||
|
{{/x-has-cookie-auth-methods}}
|
||||||
|
{{#x-has-header-auth-methods}}
|
||||||
|
token_in_header: Option<String>,
|
||||||
|
{{/x-has-header-auth-methods}}
|
||||||
|
{{/vendorExtensions}}
|
||||||
{{#headerParams.size}}
|
{{#headerParams.size}}
|
||||||
header_params: models::{{{operationIdCamelCase}}}HeaderParams,
|
header_params: models::{{{operationIdCamelCase}}}HeaderParams,
|
||||||
{{/headerParams.size}}
|
{{/headerParams.size}}
|
||||||
|
@ -7,6 +7,13 @@ async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A>(
|
|||||||
{{#headerParams.size}}
|
{{#headerParams.size}}
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
{{/headerParams.size}}
|
{{/headerParams.size}}
|
||||||
|
{{^headerParams.size}}
|
||||||
|
{{#vendorExtensions}}
|
||||||
|
{{#x-has-header-auth-methods}}
|
||||||
|
headers: HeaderMap,
|
||||||
|
{{/x-has-header-auth-methods}}
|
||||||
|
{{/vendorExtensions}}
|
||||||
|
{{/headerParams.size}}
|
||||||
{{#pathParams.size}}
|
{{#pathParams.size}}
|
||||||
Path(path_params): Path<models::{{{operationIdCamelCase}}}PathParams>,
|
Path(path_params): Path<models::{{{operationIdCamelCase}}}PathParams>,
|
||||||
{{/pathParams.size}}
|
{{/pathParams.size}}
|
||||||
@ -47,14 +54,34 @@ async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A>(
|
|||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::{{classFilename}}::{{classnamePascalCase}},
|
A: apis::{{classFilename}}::{{classnamePascalCase}}{{#vendorExtensions}}{{#x-has-cookie-auth-methods}}+ apis::CookieAuthentication{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}+ apis::ApiKeyAuthHeader{{/x-has-header-auth-methods}}{{/vendorExtensions}},
|
||||||
{
|
{
|
||||||
|
{{#vendorExtensions}}
|
||||||
|
{{#x-has-auth-methods}}
|
||||||
|
// Authentication
|
||||||
|
{{/x-has-auth-methods}}
|
||||||
|
{{#x-has-cookie-auth-methods}}
|
||||||
|
let token_in_cookie = api_impl.as_ref().extract_token_from_cookie(&cookies, "{{x-api-key-cookie-name}}");
|
||||||
|
{{/x-has-cookie-auth-methods}}
|
||||||
|
{{#x-has-header-auth-methods}}
|
||||||
|
let token_in_header = api_impl.as_ref().extract_token_from_header(&headers, "{{x-api-key-header-name}}");
|
||||||
|
{{/x-has-header-auth-methods}}
|
||||||
|
{{#x-has-auth-methods}}
|
||||||
|
if let ({{#x-has-cookie-auth-methods}}None,{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}None,{{/x-has-header-auth-methods}}) = ({{#x-has-cookie-auth-methods}}&token_in_cookie,{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}&token_in_header,{{/x-has-header-auth-methods}}) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
{{/x-has-auth-methods}}
|
||||||
|
{{/vendorExtensions}}
|
||||||
|
|
||||||
{{#headerParams}}
|
{{#headerParams}}
|
||||||
{{#-first}}
|
{{#-first}}
|
||||||
// Header parameters
|
// Header parameters
|
||||||
let header_params = {
|
let header_params = {
|
||||||
{{/-first}}
|
{{/-first}}
|
||||||
let header_{{{paramName}}} = headers.get(HeaderName::from_static("{{{nameInLowerCase}}}"));
|
let header_{{{paramName}}} = headers.get(HeaderName::from_static("{{{baseName}}}"));
|
||||||
|
|
||||||
let header_{{{paramName}}} = match header_{{{paramName}}} {
|
let header_{{{paramName}}} = match header_{{{paramName}}} {
|
||||||
Some(v) => match header::IntoHeaderValue::<{{{dataType}}}>::try_from((*v).clone()) {
|
Some(v) => match header::IntoHeaderValue::<{{{dataType}}}>::try_from((*v).clone()) {
|
||||||
@ -154,6 +181,14 @@ where
|
|||||||
method,
|
method,
|
||||||
host,
|
host,
|
||||||
cookies,
|
cookies,
|
||||||
|
{{#vendorExtensions}}
|
||||||
|
{{#x-has-cookie-auth-methods}}
|
||||||
|
token_in_cookie,
|
||||||
|
{{/x-has-cookie-auth-methods}}
|
||||||
|
{{#x-has-header-auth-methods}}
|
||||||
|
token_in_header,
|
||||||
|
{{/x-has-header-auth-methods}}
|
||||||
|
{{/vendorExtensions}}
|
||||||
{{#headerParams.size}}
|
{{#headerParams.size}}
|
||||||
header_params,
|
header_params,
|
||||||
{{/headerParams.size}}
|
{{/headerParams.size}}
|
||||||
@ -232,7 +267,7 @@ where
|
|||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(
|
response_headers.insert(
|
||||||
HeaderName::from_static("{{{nameInLowerCase}}}"),
|
HeaderName::from_static("{{{baseName}}}"),
|
||||||
{{name}}
|
{{name}}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
pub fn new<I, A>(api_impl: I) -> Router
|
pub fn new<I, A>(api_impl: I) -> Router
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Clone + Send + Sync + 'static,
|
I: AsRef<A> + Clone + Send + Sync + 'static,
|
||||||
A: {{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}} + {{/operations}}{{/apis}}{{/apiInfo}}'static,
|
A: {{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}} + {{/operations}}{{/apis}}{{/apiInfo}}{{#authMethods}}{{#isApiKey}}{{#isKeyInCookie}}apis::CookieAuthentication + {{/isKeyInCookie}}{{#isKeyInHeader}}apis::ApiKeyAuthHeader + {{/isKeyInHeader}}{{/isApiKey}}{{/authMethods}}'static,
|
||||||
{
|
{
|
||||||
// build our application with a route
|
// build our application with a route
|
||||||
Router::new()
|
Router::new()
|
||||||
|
2
samples/server/petstore/rust-axum/output/apikey-auths/.gitignore
vendored
Normal file
2
samples/server/petstore/rust-axum/output/apikey-auths/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
target
|
||||||
|
Cargo.lock
|
@ -0,0 +1,23 @@
|
|||||||
|
# OpenAPI Generator Ignore
|
||||||
|
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||||
|
|
||||||
|
# Use this file to prevent files from being overwritten by the generator.
|
||||||
|
# The patterns follow closely to .gitignore or .dockerignore.
|
||||||
|
|
||||||
|
# As an example, the C# client generator defines ApiClient.cs.
|
||||||
|
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||||
|
#ApiClient.cs
|
||||||
|
|
||||||
|
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||||
|
#foo/*/qux
|
||||||
|
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||||
|
#foo/**/qux
|
||||||
|
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can also negate patterns with an exclamation (!).
|
||||||
|
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||||
|
#docs/*.md
|
||||||
|
# Then explicitly reverse the ignore rule for a single file:
|
||||||
|
#!docs/README.md
|
@ -0,0 +1,10 @@
|
|||||||
|
.gitignore
|
||||||
|
Cargo.toml
|
||||||
|
README.md
|
||||||
|
src/apis/mod.rs
|
||||||
|
src/apis/payments.rs
|
||||||
|
src/header.rs
|
||||||
|
src/lib.rs
|
||||||
|
src/models.rs
|
||||||
|
src/server/mod.rs
|
||||||
|
src/types.rs
|
@ -0,0 +1 @@
|
|||||||
|
7.10.0-SNAPSHOT
|
@ -0,0 +1,46 @@
|
|||||||
|
[package]
|
||||||
|
name = "apikey-auths"
|
||||||
|
version = "1.0.0"
|
||||||
|
authors = ["OpenAPI Generator team and contributors"]
|
||||||
|
description = "Checkout Basic"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["server"]
|
||||||
|
server = []
|
||||||
|
conversion = [
|
||||||
|
"frunk",
|
||||||
|
"frunk_derives",
|
||||||
|
"frunk_core",
|
||||||
|
"frunk-enum-core",
|
||||||
|
"frunk-enum-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-trait = "0.1"
|
||||||
|
axum = { version = "0.7" }
|
||||||
|
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
|
||||||
|
base64 = "0.22"
|
||||||
|
bytes = "1"
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
frunk = { version = "0.4", optional = true }
|
||||||
|
frunk-enum-core = { version = "0.3", optional = true }
|
||||||
|
frunk-enum-derive = { version = "0.3", optional = true }
|
||||||
|
frunk_core = { version = "0.4", optional = true }
|
||||||
|
frunk_derives = { version = "0.4", optional = true }
|
||||||
|
http = "1"
|
||||||
|
lazy_static = "1"
|
||||||
|
regex = "1"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = { version = "1", features = ["raw_value"] }
|
||||||
|
serde_urlencoded = "0.7"
|
||||||
|
tokio = { version = "1", default-features = false, features = [
|
||||||
|
"signal",
|
||||||
|
"rt-multi-thread",
|
||||||
|
] }
|
||||||
|
tracing = { version = "0.1", features = ["attributes"] }
|
||||||
|
uuid = { version = "1", features = ["serde"] }
|
||||||
|
validator = { version = "0.18", features = ["derive"] }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tracing-subscriber = "0.3"
|
@ -0,0 +1,91 @@
|
|||||||
|
# Rust API for apikey-auths
|
||||||
|
|
||||||
|
Checkout Basic
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This server was generated by the [openapi-generator]
|
||||||
|
(https://openapi-generator.tech) project. By using the
|
||||||
|
[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote
|
||||||
|
server, you can easily generate a server stub.
|
||||||
|
|
||||||
|
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
|
||||||
|
|
||||||
|
- API version: 1.0.0
|
||||||
|
- Generator version: 7.10.0-SNAPSHOT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This autogenerated project defines an API crate `apikey-auths` which contains:
|
||||||
|
* An `Api` trait defining the API in Rust.
|
||||||
|
* Data types representing the underlying data model.
|
||||||
|
* Axum router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
|
||||||
|
* Request validations (path, query, body params) are included.
|
||||||
|
|
||||||
|
## Using the generated library
|
||||||
|
|
||||||
|
The generated library has a few optional features that can be activated through Cargo.
|
||||||
|
|
||||||
|
* `server`
|
||||||
|
* This defaults to enabled and creates the basic skeleton of a server implementation based on Axum.
|
||||||
|
* To create the server stack you'll need to provide an implementation of the API trait to provide the server function.
|
||||||
|
* `conversions`
|
||||||
|
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
|
||||||
|
|
||||||
|
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ServerImpl {
|
||||||
|
// database: sea_orm::DbConn,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
#[async_trait]
|
||||||
|
impl apikey-auths::Api for ServerImpl {
|
||||||
|
// API implementation goes here
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_server(addr: &str) {
|
||||||
|
// initialize tracing
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
// Init Axum router
|
||||||
|
let app = apikey-auths::server::new(Arc::new(ServerImpl));
|
||||||
|
|
||||||
|
// Add layers to the router
|
||||||
|
let app = app.layer(...);
|
||||||
|
|
||||||
|
// Run the server with graceful shutdown
|
||||||
|
let listener = TcpListener::bind(addr).await.unwrap();
|
||||||
|
axum::serve(listener, app)
|
||||||
|
.with_graceful_shutdown(shutdown_signal())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn shutdown_signal() {
|
||||||
|
let ctrl_c = async {
|
||||||
|
signal::ctrl_c()
|
||||||
|
.await
|
||||||
|
.expect("failed to install Ctrl+C handler");
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let terminate = async {
|
||||||
|
signal::unix::signal(signal::unix::SignalKind::terminate())
|
||||||
|
.expect("failed to install signal handler")
|
||||||
|
.recv()
|
||||||
|
.await;
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
let terminate = std::future::pending::<()>();
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
_ = ctrl_c => {},
|
||||||
|
_ = terminate => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -0,0 +1,18 @@
|
|||||||
|
pub mod payments;
|
||||||
|
|
||||||
|
/// API Key Authentication - Header.
|
||||||
|
pub trait ApiKeyAuthHeader {
|
||||||
|
fn extract_token_from_header(
|
||||||
|
&self,
|
||||||
|
headers: &axum::http::header::HeaderMap,
|
||||||
|
key: &str,
|
||||||
|
) -> Option<String>;
|
||||||
|
}
|
||||||
|
/// Cookie Authentication.
|
||||||
|
pub trait CookieAuthentication {
|
||||||
|
fn extract_token_from_cookie(
|
||||||
|
&self,
|
||||||
|
cookies: &axum_extra::extract::CookieJar,
|
||||||
|
key: &str,
|
||||||
|
) -> Option<String>;
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use axum::extract::*;
|
||||||
|
use axum_extra::extract::{CookieJar, Multipart};
|
||||||
|
use bytes::Bytes;
|
||||||
|
use http::Method;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{models, types::*};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[must_use]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum GetPaymentMethodByIdResponse {
|
||||||
|
/// OK - the request has succeeded.
|
||||||
|
Status200_OK(models::PaymentMethod),
|
||||||
|
/// Unprocessable Entity - a request validation error.
|
||||||
|
Status422_UnprocessableEntity(models::CheckoutError),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[must_use]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum GetPaymentMethodsResponse {
|
||||||
|
/// OK - the request has succeeded.
|
||||||
|
Status200_OK(Vec<models::PaymentMethod>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[must_use]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum PostMakePaymentResponse {
|
||||||
|
/// OK - the request has succeeded.
|
||||||
|
Status200_OK(models::PaymentResult),
|
||||||
|
/// Unprocessable Entity - a request validation error.
|
||||||
|
Status422_UnprocessableEntity(models::CheckoutError),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Payments
|
||||||
|
#[async_trait]
|
||||||
|
#[allow(clippy::ptr_arg)]
|
||||||
|
pub trait Payments {
|
||||||
|
/// Get payment method by id.
|
||||||
|
///
|
||||||
|
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
|
||||||
|
async fn get_payment_method_by_id(
|
||||||
|
&self,
|
||||||
|
method: Method,
|
||||||
|
host: Host,
|
||||||
|
cookies: CookieJar,
|
||||||
|
path_params: models::GetPaymentMethodByIdPathParams,
|
||||||
|
) -> Result<GetPaymentMethodByIdResponse, String>;
|
||||||
|
|
||||||
|
/// Get payment methods.
|
||||||
|
///
|
||||||
|
/// GetPaymentMethods - GET /v71/paymentMethods
|
||||||
|
async fn get_payment_methods(
|
||||||
|
&self,
|
||||||
|
method: Method,
|
||||||
|
host: Host,
|
||||||
|
cookies: CookieJar,
|
||||||
|
) -> Result<GetPaymentMethodsResponse, String>;
|
||||||
|
|
||||||
|
/// Make a payment.
|
||||||
|
///
|
||||||
|
/// PostMakePayment - POST /v71/payments
|
||||||
|
async fn post_make_payment(
|
||||||
|
&self,
|
||||||
|
method: Method,
|
||||||
|
host: Host,
|
||||||
|
cookies: CookieJar,
|
||||||
|
token_in_cookie: Option<String>,
|
||||||
|
body: Option<models::Payment>,
|
||||||
|
) -> Result<PostMakePaymentResponse, String>;
|
||||||
|
}
|
@ -0,0 +1,197 @@
|
|||||||
|
use std::{convert::TryFrom, fmt, ops::Deref};
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use http::HeaderValue;
|
||||||
|
|
||||||
|
/// A struct to allow homogeneous conversion into a HeaderValue. We can't
|
||||||
|
/// implement the From/Into trait on HeaderValue because we don't own
|
||||||
|
/// either of the types.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct IntoHeaderValue<T>(pub T);
|
||||||
|
|
||||||
|
// Generic implementations
|
||||||
|
|
||||||
|
impl<T> Deref for IntoHeaderValue<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derive for each TryFrom<T> in http::HeaderValue
|
||||||
|
|
||||||
|
macro_rules! ihv_generate {
|
||||||
|
($t:ident) => {
|
||||||
|
impl TryFrom<HeaderValue> for IntoHeaderValue<$t> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
Ok(hdr_value) => match hdr_value.parse::<$t>() {
|
||||||
|
Ok(hdr_value) => Ok(IntoHeaderValue(hdr_value)),
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to parse {} as a string: {}",
|
||||||
|
stringify!($t),
|
||||||
|
e
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to parse header {:?} as a string - {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<IntoHeaderValue<$t>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: IntoHeaderValue<$t>) -> Result<Self, Self::Error> {
|
||||||
|
Ok(hdr_value.0.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ihv_generate!(u64);
|
||||||
|
ihv_generate!(i64);
|
||||||
|
ihv_generate!(i16);
|
||||||
|
ihv_generate!(u16);
|
||||||
|
ihv_generate!(u32);
|
||||||
|
ihv_generate!(usize);
|
||||||
|
ihv_generate!(isize);
|
||||||
|
ihv_generate!(i32);
|
||||||
|
|
||||||
|
// Custom derivations
|
||||||
|
|
||||||
|
// Vec<String>
|
||||||
|
|
||||||
|
impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
Ok(hdr_value) => Ok(IntoHeaderValue(
|
||||||
|
hdr_value
|
||||||
|
.split(',')
|
||||||
|
.filter_map(|x| match x.trim() {
|
||||||
|
"" => None,
|
||||||
|
y => Some(y.to_string()),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)),
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to parse header: {:?} as a string - {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: IntoHeaderValue<Vec<String>>) -> Result<Self, Self::Error> {
|
||||||
|
match HeaderValue::from_str(&hdr_value.0.join(", ")) {
|
||||||
|
Ok(hdr_value) => Ok(hdr_value),
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to convert {:?} into a header - {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String
|
||||||
|
|
||||||
|
impl TryFrom<HeaderValue> for IntoHeaderValue<String> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
Ok(hdr_value) => Ok(IntoHeaderValue(hdr_value.to_string())),
|
||||||
|
Err(e) => Err(format!("Unable to convert header {:?} to {}", hdr_value, e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: IntoHeaderValue<String>) -> Result<Self, Self::Error> {
|
||||||
|
match HeaderValue::from_str(&hdr_value.0) {
|
||||||
|
Ok(hdr_value) => Ok(hdr_value),
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to convert {:?} from a header {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool
|
||||||
|
|
||||||
|
impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
Ok(hdr_value) => match hdr_value.parse() {
|
||||||
|
Ok(hdr_value) => Ok(IntoHeaderValue(hdr_value)),
|
||||||
|
Err(e) => Err(format!("Unable to parse bool from {} - {}", hdr_value, e)),
|
||||||
|
},
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to convert {:?} from a header {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: IntoHeaderValue<bool>) -> Result<Self, Self::Error> {
|
||||||
|
match HeaderValue::from_str(&hdr_value.0.to_string()) {
|
||||||
|
Ok(hdr_value) => Ok(hdr_value),
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to convert: {:?} into a header: {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DateTime
|
||||||
|
|
||||||
|
impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
Ok(hdr_value) => match DateTime::parse_from_rfc3339(hdr_value) {
|
||||||
|
Ok(date) => Ok(IntoHeaderValue(date.with_timezone(&Utc))),
|
||||||
|
Err(e) => Err(format!("Unable to parse: {} as date - {}", hdr_value, e)),
|
||||||
|
},
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to convert header {:?} to string {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: IntoHeaderValue<DateTime<Utc>>) -> Result<Self, Self::Error> {
|
||||||
|
match HeaderValue::from_str(hdr_value.0.to_rfc3339().as_str()) {
|
||||||
|
Ok(hdr_value) => Ok(hdr_value),
|
||||||
|
Err(e) => Err(format!(
|
||||||
|
"Unable to convert {:?} to a header: {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
#![allow(
|
||||||
|
missing_docs,
|
||||||
|
trivial_casts,
|
||||||
|
unused_variables,
|
||||||
|
unused_mut,
|
||||||
|
unused_extern_crates,
|
||||||
|
non_camel_case_types,
|
||||||
|
unused_imports,
|
||||||
|
unused_attributes
|
||||||
|
)]
|
||||||
|
#![allow(
|
||||||
|
clippy::derive_partial_eq_without_eq,
|
||||||
|
clippy::disallowed_names,
|
||||||
|
clippy::too_many_arguments
|
||||||
|
)]
|
||||||
|
|
||||||
|
pub const BASE_PATH: &str = "/v71";
|
||||||
|
pub const API_VERSION: &str = "1.0.0";
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
pub mod server;
|
||||||
|
|
||||||
|
pub mod apis;
|
||||||
|
pub mod models;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
pub(crate) mod header;
|
@ -0,0 +1,841 @@
|
|||||||
|
#![allow(unused_qualifications)]
|
||||||
|
|
||||||
|
use http::HeaderValue;
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
use crate::header;
|
||||||
|
use crate::{models, types::*};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||||
|
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||||
|
pub struct GetPaymentMethodByIdPathParams {
|
||||||
|
/// Id of the payment method
|
||||||
|
pub id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||||
|
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||||
|
pub struct Amount {
|
||||||
|
/// The three-character [ISO currency code](https://docs.adyen.com/development-resources/currency-codes).
|
||||||
|
#[serde(rename = "currency")]
|
||||||
|
#[validate(length(min = 3, max = 3))]
|
||||||
|
pub currency: String,
|
||||||
|
|
||||||
|
/// The amount of the transaction, in [minor units](https://docs.adyen.com/development-resources/currency-codes).
|
||||||
|
#[serde(rename = "value")]
|
||||||
|
pub value: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Amount {
|
||||||
|
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
|
||||||
|
pub fn new(currency: String, value: i64) -> Amount {
|
||||||
|
Amount { currency, value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the Amount value to the Query Parameters representation (style=form, explode=false)
|
||||||
|
/// specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde serializer
|
||||||
|
impl std::fmt::Display for Amount {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let params: Vec<Option<String>> = vec![
|
||||||
|
Some("currency".to_string()),
|
||||||
|
Some(self.currency.to_string()),
|
||||||
|
Some("value".to_string()),
|
||||||
|
Some(self.value.to_string()),
|
||||||
|
];
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
params.into_iter().flatten().collect::<Vec<_>>().join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts Query Parameters representation (style=form, explode=false) to a Amount value
|
||||||
|
/// as specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde deserializer
|
||||||
|
impl std::str::FromStr for Amount {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
/// An intermediate representation of the struct to use for parsing.
|
||||||
|
#[derive(Default)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct IntermediateRep {
|
||||||
|
pub currency: Vec<String>,
|
||||||
|
pub value: Vec<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut intermediate_rep = IntermediateRep::default();
|
||||||
|
|
||||||
|
// Parse into intermediate representation
|
||||||
|
let mut string_iter = s.split(',');
|
||||||
|
let mut key_result = string_iter.next();
|
||||||
|
|
||||||
|
while key_result.is_some() {
|
||||||
|
let val = match string_iter.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Missing value while parsing Amount".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(key) = key_result {
|
||||||
|
#[allow(clippy::match_single_binding)]
|
||||||
|
match key {
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"currency" => intermediate_rep.currency.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"value" => intermediate_rep.value.push(
|
||||||
|
<i64 as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Unexpected key while parsing Amount".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next key
|
||||||
|
key_result = string_iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the intermediate representation to return the struct
|
||||||
|
std::result::Result::Ok(Amount {
|
||||||
|
currency: intermediate_rep
|
||||||
|
.currency
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "currency missing in Amount".to_string())?,
|
||||||
|
value: intermediate_rep
|
||||||
|
.value
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "value missing in Amount".to_string())?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for converting between header::IntoHeaderValue<Amount> and HeaderValue
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<header::IntoHeaderValue<Amount>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
hdr_value: header::IntoHeaderValue<Amount>,
|
||||||
|
) -> std::result::Result<Self, Self::Error> {
|
||||||
|
let hdr_value = hdr_value.to_string();
|
||||||
|
match HeaderValue::from_str(&hdr_value) {
|
||||||
|
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Invalid header value for Amount - value: {} is invalid {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Amount> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> std::result::Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
match <Amount as std::str::FromStr>::from_str(value) {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||||
|
}
|
||||||
|
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header value '{}' into Amount - {}",
|
||||||
|
value, err
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header: {:?} to string: {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||||
|
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||||
|
pub struct CheckoutError {
|
||||||
|
/// Error code
|
||||||
|
#[serde(rename = "code")]
|
||||||
|
pub code: String,
|
||||||
|
|
||||||
|
/// User-friendly message
|
||||||
|
#[serde(rename = "message")]
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CheckoutError {
|
||||||
|
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
|
||||||
|
pub fn new(code: String, message: String) -> CheckoutError {
|
||||||
|
CheckoutError { code, message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the CheckoutError value to the Query Parameters representation (style=form, explode=false)
|
||||||
|
/// specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde serializer
|
||||||
|
impl std::fmt::Display for CheckoutError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let params: Vec<Option<String>> = vec![
|
||||||
|
Some("code".to_string()),
|
||||||
|
Some(self.code.to_string()),
|
||||||
|
Some("message".to_string()),
|
||||||
|
Some(self.message.to_string()),
|
||||||
|
];
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
params.into_iter().flatten().collect::<Vec<_>>().join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts Query Parameters representation (style=form, explode=false) to a CheckoutError value
|
||||||
|
/// as specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde deserializer
|
||||||
|
impl std::str::FromStr for CheckoutError {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
/// An intermediate representation of the struct to use for parsing.
|
||||||
|
#[derive(Default)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct IntermediateRep {
|
||||||
|
pub code: Vec<String>,
|
||||||
|
pub message: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut intermediate_rep = IntermediateRep::default();
|
||||||
|
|
||||||
|
// Parse into intermediate representation
|
||||||
|
let mut string_iter = s.split(',');
|
||||||
|
let mut key_result = string_iter.next();
|
||||||
|
|
||||||
|
while key_result.is_some() {
|
||||||
|
let val = match string_iter.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Missing value while parsing CheckoutError".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(key) = key_result {
|
||||||
|
#[allow(clippy::match_single_binding)]
|
||||||
|
match key {
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"code" => intermediate_rep.code.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"message" => intermediate_rep.message.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Unexpected key while parsing CheckoutError".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next key
|
||||||
|
key_result = string_iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the intermediate representation to return the struct
|
||||||
|
std::result::Result::Ok(CheckoutError {
|
||||||
|
code: intermediate_rep
|
||||||
|
.code
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "code missing in CheckoutError".to_string())?,
|
||||||
|
message: intermediate_rep
|
||||||
|
.message
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "message missing in CheckoutError".to_string())?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for converting between header::IntoHeaderValue<CheckoutError> and HeaderValue
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<header::IntoHeaderValue<CheckoutError>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
hdr_value: header::IntoHeaderValue<CheckoutError>,
|
||||||
|
) -> std::result::Result<Self, Self::Error> {
|
||||||
|
let hdr_value = hdr_value.to_string();
|
||||||
|
match HeaderValue::from_str(&hdr_value) {
|
||||||
|
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Invalid header value for CheckoutError - value: {} is invalid {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<CheckoutError> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> std::result::Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
match <CheckoutError as std::str::FromStr>::from_str(value) {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||||
|
}
|
||||||
|
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header value '{}' into CheckoutError - {}",
|
||||||
|
value, err
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header: {:?} to string: {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||||
|
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||||
|
pub struct Payment {
|
||||||
|
#[serde(rename = "paymentMethod")]
|
||||||
|
pub payment_method: models::PaymentMethod,
|
||||||
|
|
||||||
|
#[serde(rename = "amount")]
|
||||||
|
pub amount: models::Amount,
|
||||||
|
|
||||||
|
#[serde(rename = "merchantAccount")]
|
||||||
|
pub merchant_account: String,
|
||||||
|
|
||||||
|
#[serde(rename = "reference")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub reference: Option<String>,
|
||||||
|
|
||||||
|
/// Note: inline enums are not fully supported by openapi-generator
|
||||||
|
#[serde(rename = "channel")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub channel: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Payment {
|
||||||
|
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
|
||||||
|
pub fn new(
|
||||||
|
payment_method: models::PaymentMethod,
|
||||||
|
amount: models::Amount,
|
||||||
|
merchant_account: String,
|
||||||
|
) -> Payment {
|
||||||
|
Payment {
|
||||||
|
payment_method,
|
||||||
|
amount,
|
||||||
|
merchant_account,
|
||||||
|
reference: None,
|
||||||
|
channel: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the Payment value to the Query Parameters representation (style=form, explode=false)
|
||||||
|
/// specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde serializer
|
||||||
|
impl std::fmt::Display for Payment {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let params: Vec<Option<String>> = vec![
|
||||||
|
// Skipping paymentMethod in query parameter serialization
|
||||||
|
|
||||||
|
// Skipping amount in query parameter serialization
|
||||||
|
Some("merchantAccount".to_string()),
|
||||||
|
Some(self.merchant_account.to_string()),
|
||||||
|
self.reference
|
||||||
|
.as_ref()
|
||||||
|
.map(|reference| ["reference".to_string(), reference.to_string()].join(",")),
|
||||||
|
self.channel
|
||||||
|
.as_ref()
|
||||||
|
.map(|channel| ["channel".to_string(), channel.to_string()].join(",")),
|
||||||
|
];
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
params.into_iter().flatten().collect::<Vec<_>>().join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts Query Parameters representation (style=form, explode=false) to a Payment value
|
||||||
|
/// as specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde deserializer
|
||||||
|
impl std::str::FromStr for Payment {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
/// An intermediate representation of the struct to use for parsing.
|
||||||
|
#[derive(Default)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct IntermediateRep {
|
||||||
|
pub payment_method: Vec<models::PaymentMethod>,
|
||||||
|
pub amount: Vec<models::Amount>,
|
||||||
|
pub merchant_account: Vec<String>,
|
||||||
|
pub reference: Vec<String>,
|
||||||
|
pub channel: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut intermediate_rep = IntermediateRep::default();
|
||||||
|
|
||||||
|
// Parse into intermediate representation
|
||||||
|
let mut string_iter = s.split(',');
|
||||||
|
let mut key_result = string_iter.next();
|
||||||
|
|
||||||
|
while key_result.is_some() {
|
||||||
|
let val = match string_iter.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Missing value while parsing Payment".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(key) = key_result {
|
||||||
|
#[allow(clippy::match_single_binding)]
|
||||||
|
match key {
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"paymentMethod" => intermediate_rep.payment_method.push(
|
||||||
|
<models::PaymentMethod as std::str::FromStr>::from_str(val)
|
||||||
|
.map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"amount" => intermediate_rep.amount.push(
|
||||||
|
<models::Amount as std::str::FromStr>::from_str(val)
|
||||||
|
.map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"merchantAccount" => intermediate_rep.merchant_account.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"reference" => intermediate_rep.reference.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"channel" => intermediate_rep.channel.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Unexpected key while parsing Payment".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next key
|
||||||
|
key_result = string_iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the intermediate representation to return the struct
|
||||||
|
std::result::Result::Ok(Payment {
|
||||||
|
payment_method: intermediate_rep
|
||||||
|
.payment_method
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "paymentMethod missing in Payment".to_string())?,
|
||||||
|
amount: intermediate_rep
|
||||||
|
.amount
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "amount missing in Payment".to_string())?,
|
||||||
|
merchant_account: intermediate_rep
|
||||||
|
.merchant_account
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "merchantAccount missing in Payment".to_string())?,
|
||||||
|
reference: intermediate_rep.reference.into_iter().next(),
|
||||||
|
channel: intermediate_rep.channel.into_iter().next(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for converting between header::IntoHeaderValue<Payment> and HeaderValue
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<header::IntoHeaderValue<Payment>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
hdr_value: header::IntoHeaderValue<Payment>,
|
||||||
|
) -> std::result::Result<Self, Self::Error> {
|
||||||
|
let hdr_value = hdr_value.to_string();
|
||||||
|
match HeaderValue::from_str(&hdr_value) {
|
||||||
|
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Invalid header value for Payment - value: {} is invalid {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Payment> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> std::result::Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
match <Payment as std::str::FromStr>::from_str(value) {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||||
|
}
|
||||||
|
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header value '{}' into Payment - {}",
|
||||||
|
value, err
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header: {:?} to string: {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||||
|
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||||
|
pub struct PaymentMethod {
|
||||||
|
/// Name of the payment method
|
||||||
|
/// Note: inline enums are not fully supported by openapi-generator
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub name: Option<String>,
|
||||||
|
|
||||||
|
/// Type of the payment method
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub r#type: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PaymentMethod {
|
||||||
|
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
|
||||||
|
pub fn new() -> PaymentMethod {
|
||||||
|
PaymentMethod {
|
||||||
|
name: None,
|
||||||
|
r#type: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the PaymentMethod value to the Query Parameters representation (style=form, explode=false)
|
||||||
|
/// specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde serializer
|
||||||
|
impl std::fmt::Display for PaymentMethod {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let params: Vec<Option<String>> = vec![
|
||||||
|
self.name
|
||||||
|
.as_ref()
|
||||||
|
.map(|name| ["name".to_string(), name.to_string()].join(",")),
|
||||||
|
self.r#type
|
||||||
|
.as_ref()
|
||||||
|
.map(|r#type| ["type".to_string(), r#type.to_string()].join(",")),
|
||||||
|
];
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
params.into_iter().flatten().collect::<Vec<_>>().join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts Query Parameters representation (style=form, explode=false) to a PaymentMethod value
|
||||||
|
/// as specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde deserializer
|
||||||
|
impl std::str::FromStr for PaymentMethod {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
/// An intermediate representation of the struct to use for parsing.
|
||||||
|
#[derive(Default)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct IntermediateRep {
|
||||||
|
pub name: Vec<String>,
|
||||||
|
pub r#type: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut intermediate_rep = IntermediateRep::default();
|
||||||
|
|
||||||
|
// Parse into intermediate representation
|
||||||
|
let mut string_iter = s.split(',');
|
||||||
|
let mut key_result = string_iter.next();
|
||||||
|
|
||||||
|
while key_result.is_some() {
|
||||||
|
let val = match string_iter.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Missing value while parsing PaymentMethod".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(key) = key_result {
|
||||||
|
#[allow(clippy::match_single_binding)]
|
||||||
|
match key {
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"name" => intermediate_rep.name.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"type" => intermediate_rep.r#type.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Unexpected key while parsing PaymentMethod".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next key
|
||||||
|
key_result = string_iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the intermediate representation to return the struct
|
||||||
|
std::result::Result::Ok(PaymentMethod {
|
||||||
|
name: intermediate_rep.name.into_iter().next(),
|
||||||
|
r#type: intermediate_rep.r#type.into_iter().next(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for converting between header::IntoHeaderValue<PaymentMethod> and HeaderValue
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<header::IntoHeaderValue<PaymentMethod>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
hdr_value: header::IntoHeaderValue<PaymentMethod>,
|
||||||
|
) -> std::result::Result<Self, Self::Error> {
|
||||||
|
let hdr_value = hdr_value.to_string();
|
||||||
|
match HeaderValue::from_str(&hdr_value) {
|
||||||
|
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Invalid header value for PaymentMethod - value: {} is invalid {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<PaymentMethod> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> std::result::Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
match <PaymentMethod as std::str::FromStr>::from_str(value) {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||||
|
}
|
||||||
|
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header value '{}' into PaymentMethod - {}",
|
||||||
|
value, err
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header: {:?} to string: {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||||
|
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||||
|
pub struct PaymentResult {
|
||||||
|
/// PSP ref
|
||||||
|
#[serde(rename = "pspReference")]
|
||||||
|
pub psp_reference: String,
|
||||||
|
|
||||||
|
/// Result code
|
||||||
|
/// Note: inline enums are not fully supported by openapi-generator
|
||||||
|
#[serde(rename = "resultCode")]
|
||||||
|
pub result_code: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PaymentResult {
|
||||||
|
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
|
||||||
|
pub fn new(psp_reference: String, result_code: String) -> PaymentResult {
|
||||||
|
PaymentResult {
|
||||||
|
psp_reference,
|
||||||
|
result_code,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the PaymentResult value to the Query Parameters representation (style=form, explode=false)
|
||||||
|
/// specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde serializer
|
||||||
|
impl std::fmt::Display for PaymentResult {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let params: Vec<Option<String>> = vec![
|
||||||
|
Some("pspReference".to_string()),
|
||||||
|
Some(self.psp_reference.to_string()),
|
||||||
|
Some("resultCode".to_string()),
|
||||||
|
Some(self.result_code.to_string()),
|
||||||
|
];
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
params.into_iter().flatten().collect::<Vec<_>>().join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts Query Parameters representation (style=form, explode=false) to a PaymentResult value
|
||||||
|
/// as specified in https://swagger.io/docs/specification/serialization/
|
||||||
|
/// Should be implemented in a serde deserializer
|
||||||
|
impl std::str::FromStr for PaymentResult {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
/// An intermediate representation of the struct to use for parsing.
|
||||||
|
#[derive(Default)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct IntermediateRep {
|
||||||
|
pub psp_reference: Vec<String>,
|
||||||
|
pub result_code: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut intermediate_rep = IntermediateRep::default();
|
||||||
|
|
||||||
|
// Parse into intermediate representation
|
||||||
|
let mut string_iter = s.split(',');
|
||||||
|
let mut key_result = string_iter.next();
|
||||||
|
|
||||||
|
while key_result.is_some() {
|
||||||
|
let val = match string_iter.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Missing value while parsing PaymentResult".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(key) = key_result {
|
||||||
|
#[allow(clippy::match_single_binding)]
|
||||||
|
match key {
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"pspReference" => intermediate_rep.psp_reference.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
#[allow(clippy::redundant_clone)]
|
||||||
|
"resultCode" => intermediate_rep.result_code.push(
|
||||||
|
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"Unexpected key while parsing PaymentResult".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next key
|
||||||
|
key_result = string_iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the intermediate representation to return the struct
|
||||||
|
std::result::Result::Ok(PaymentResult {
|
||||||
|
psp_reference: intermediate_rep
|
||||||
|
.psp_reference
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "pspReference missing in PaymentResult".to_string())?,
|
||||||
|
result_code: intermediate_rep
|
||||||
|
.result_code
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "resultCode missing in PaymentResult".to_string())?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for converting between header::IntoHeaderValue<PaymentResult> and HeaderValue
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<header::IntoHeaderValue<PaymentResult>> for HeaderValue {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
hdr_value: header::IntoHeaderValue<PaymentResult>,
|
||||||
|
) -> std::result::Result<Self, Self::Error> {
|
||||||
|
let hdr_value = hdr_value.to_string();
|
||||||
|
match HeaderValue::from_str(&hdr_value) {
|
||||||
|
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Invalid header value for PaymentResult - value: {} is invalid {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<PaymentResult> {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(hdr_value: HeaderValue) -> std::result::Result<Self, Self::Error> {
|
||||||
|
match hdr_value.to_str() {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
match <PaymentResult as std::str::FromStr>::from_str(value) {
|
||||||
|
std::result::Result::Ok(value) => {
|
||||||
|
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||||
|
}
|
||||||
|
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header value '{}' into PaymentResult - {}",
|
||||||
|
value, err
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||||
|
"Unable to convert header: {:?} to string: {}",
|
||||||
|
hdr_value, e
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,330 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||||
|
use axum_extra::extract::{CookieJar, Multipart};
|
||||||
|
use bytes::Bytes;
|
||||||
|
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||||
|
use tracing::error;
|
||||||
|
use validator::{Validate, ValidationErrors};
|
||||||
|
|
||||||
|
use crate::{header, types::*};
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use crate::{apis, models};
|
||||||
|
|
||||||
|
/// Setup API Server.
|
||||||
|
pub fn new<I, A>(api_impl: I) -> Router
|
||||||
|
where
|
||||||
|
I: AsRef<A> + Clone + Send + Sync + 'static,
|
||||||
|
A: apis::payments::Payments + apis::ApiKeyAuthHeader + apis::CookieAuthentication + 'static,
|
||||||
|
{
|
||||||
|
// build our application with a route
|
||||||
|
Router::new()
|
||||||
|
.route("/v71/paymentMethods", get(get_payment_methods::<I, A>))
|
||||||
|
.route(
|
||||||
|
"/v71/paymentMethods/:id",
|
||||||
|
get(get_payment_method_by_id::<I, A>),
|
||||||
|
)
|
||||||
|
.route("/v71/payments", post(post_make_payment::<I, A>))
|
||||||
|
.with_state(api_impl)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
fn get_payment_method_by_id_validation(
|
||||||
|
path_params: models::GetPaymentMethodByIdPathParams,
|
||||||
|
) -> std::result::Result<(models::GetPaymentMethodByIdPathParams,), ValidationErrors> {
|
||||||
|
path_params.validate()?;
|
||||||
|
|
||||||
|
Ok((path_params,))
|
||||||
|
}
|
||||||
|
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
async fn get_payment_method_by_id<I, A>(
|
||||||
|
method: Method,
|
||||||
|
host: Host,
|
||||||
|
cookies: CookieJar,
|
||||||
|
Path(path_params): Path<models::GetPaymentMethodByIdPathParams>,
|
||||||
|
State(api_impl): State<I>,
|
||||||
|
) -> Result<Response, StatusCode>
|
||||||
|
where
|
||||||
|
I: AsRef<A> + Send + Sync,
|
||||||
|
A: apis::payments::Payments,
|
||||||
|
{
|
||||||
|
#[allow(clippy::redundant_closure)]
|
||||||
|
let validation =
|
||||||
|
tokio::task::spawn_blocking(move || get_payment_method_by_id_validation(path_params))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let Ok((path_params,)) = validation else {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::BAD_REQUEST)
|
||||||
|
.body(Body::from(validation.unwrap_err().to_string()))
|
||||||
|
.map_err(|_| StatusCode::BAD_REQUEST);
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.get_payment_method_by_id(method, host, cookies, path_params)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let mut response = Response::builder();
|
||||||
|
|
||||||
|
let resp = match result {
|
||||||
|
Ok(rsp) => match rsp {
|
||||||
|
apis::payments::GetPaymentMethodByIdResponse::Status200_OK(body) => {
|
||||||
|
let mut response = response.status(200);
|
||||||
|
{
|
||||||
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
|
response_headers.insert(
|
||||||
|
CONTENT_TYPE,
|
||||||
|
HeaderValue::from_str("application/json").map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_content = tokio::task::spawn_blocking(move || {
|
||||||
|
serde_json::to_vec(&body).map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
response.body(Body::from(body_content))
|
||||||
|
}
|
||||||
|
apis::payments::GetPaymentMethodByIdResponse::Status422_UnprocessableEntity(body) => {
|
||||||
|
let mut response = response.status(422);
|
||||||
|
{
|
||||||
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
|
response_headers.insert(
|
||||||
|
CONTENT_TYPE,
|
||||||
|
HeaderValue::from_str("application/json").map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_content = tokio::task::spawn_blocking(move || {
|
||||||
|
serde_json::to_vec(&body).map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
response.body(Body::from(body_content))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// Application code returned an error. This should not happen, as the implementation should
|
||||||
|
// return a valid response.
|
||||||
|
response.status(500).body(Body::empty())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
resp.map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
fn get_payment_methods_validation() -> std::result::Result<(), ValidationErrors> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/// GetPaymentMethods - GET /v71/paymentMethods
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
async fn get_payment_methods<I, A>(
|
||||||
|
method: Method,
|
||||||
|
host: Host,
|
||||||
|
cookies: CookieJar,
|
||||||
|
State(api_impl): State<I>,
|
||||||
|
) -> Result<Response, StatusCode>
|
||||||
|
where
|
||||||
|
I: AsRef<A> + Send + Sync,
|
||||||
|
A: apis::payments::Payments,
|
||||||
|
{
|
||||||
|
#[allow(clippy::redundant_closure)]
|
||||||
|
let validation = tokio::task::spawn_blocking(move || get_payment_methods_validation())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let Ok(()) = validation else {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::BAD_REQUEST)
|
||||||
|
.body(Body::from(validation.unwrap_err().to_string()))
|
||||||
|
.map_err(|_| StatusCode::BAD_REQUEST);
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.get_payment_methods(method, host, cookies)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let mut response = Response::builder();
|
||||||
|
|
||||||
|
let resp = match result {
|
||||||
|
Ok(rsp) => match rsp {
|
||||||
|
apis::payments::GetPaymentMethodsResponse::Status200_OK(body) => {
|
||||||
|
let mut response = response.status(200);
|
||||||
|
{
|
||||||
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
|
response_headers.insert(
|
||||||
|
CONTENT_TYPE,
|
||||||
|
HeaderValue::from_str("application/json").map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_content = tokio::task::spawn_blocking(move || {
|
||||||
|
serde_json::to_vec(&body).map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
response.body(Body::from(body_content))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// Application code returned an error. This should not happen, as the implementation should
|
||||||
|
// return a valid response.
|
||||||
|
response.status(500).body(Body::empty())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
resp.map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(validator::Validate)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct PostMakePaymentBodyValidator<'a> {
|
||||||
|
#[validate(nested)]
|
||||||
|
body: &'a models::Payment,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
fn post_make_payment_validation(
|
||||||
|
body: Option<models::Payment>,
|
||||||
|
) -> std::result::Result<(Option<models::Payment>,), ValidationErrors> {
|
||||||
|
if let Some(body) = &body {
|
||||||
|
let b = PostMakePaymentBodyValidator { body };
|
||||||
|
b.validate()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((body,))
|
||||||
|
}
|
||||||
|
/// PostMakePayment - POST /v71/payments
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
async fn post_make_payment<I, A>(
|
||||||
|
method: Method,
|
||||||
|
host: Host,
|
||||||
|
cookies: CookieJar,
|
||||||
|
State(api_impl): State<I>,
|
||||||
|
Json(body): Json<Option<models::Payment>>,
|
||||||
|
) -> Result<Response, StatusCode>
|
||||||
|
where
|
||||||
|
I: AsRef<A> + Send + Sync,
|
||||||
|
A: apis::payments::Payments + apis::CookieAuthentication,
|
||||||
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_cookie = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_cookie(&cookies, "XApiKey");
|
||||||
|
if let (None,) = (&token_in_cookie,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::redundant_closure)]
|
||||||
|
let validation = tokio::task::spawn_blocking(move || post_make_payment_validation(body))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let Ok((body,)) = validation else {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::BAD_REQUEST)
|
||||||
|
.body(Body::from(validation.unwrap_err().to_string()))
|
||||||
|
.map_err(|_| StatusCode::BAD_REQUEST);
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.post_make_payment(method, host, cookies, token_in_cookie, body)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let mut response = Response::builder();
|
||||||
|
|
||||||
|
let resp = match result {
|
||||||
|
Ok(rsp) => match rsp {
|
||||||
|
apis::payments::PostMakePaymentResponse::Status200_OK(body) => {
|
||||||
|
let mut response = response.status(200);
|
||||||
|
{
|
||||||
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
|
response_headers.insert(
|
||||||
|
CONTENT_TYPE,
|
||||||
|
HeaderValue::from_str("application/json").map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_content = tokio::task::spawn_blocking(move || {
|
||||||
|
serde_json::to_vec(&body).map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
response.body(Body::from(body_content))
|
||||||
|
}
|
||||||
|
apis::payments::PostMakePaymentResponse::Status422_UnprocessableEntity(body) => {
|
||||||
|
let mut response = response.status(422);
|
||||||
|
{
|
||||||
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
|
response_headers.insert(
|
||||||
|
CONTENT_TYPE,
|
||||||
|
HeaderValue::from_str("application/json").map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_content = tokio::task::spawn_blocking(move || {
|
||||||
|
serde_json::to_vec(&body).map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
response.body(Body::from(body_content))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// Application code returned an error. This should not happen, as the implementation should
|
||||||
|
// return a valid response.
|
||||||
|
response.status(500).body(Body::empty())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
resp.map_err(|e| {
|
||||||
|
error!(error = ?e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})
|
||||||
|
}
|
@ -0,0 +1,665 @@
|
|||||||
|
use std::{mem, str::FromStr};
|
||||||
|
|
||||||
|
use base64::{engine::general_purpose, Engine};
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Object(serde_json::Value);
|
||||||
|
|
||||||
|
impl validator::Validate for Object {
|
||||||
|
fn validate(&self) -> Result<(), validator::ValidationErrors> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Object {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(Self(serde_json::Value::String(s.to_owned())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serde helper function to create a default `Option<Nullable<T>>` while
|
||||||
|
/// deserializing
|
||||||
|
pub fn default_optional_nullable<T>() -> Option<Nullable<T>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serde helper function to deserialize into an `Option<Nullable<T>>`
|
||||||
|
pub fn deserialize_optional_nullable<'de, D, T>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<Option<Nullable<T>>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
T: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
Option::<T>::deserialize(deserializer).map(|val| match val {
|
||||||
|
Some(inner) => Some(Nullable::Present(inner)),
|
||||||
|
None => Some(Nullable::Null),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Nullable type. Represents a value which may be specified as null on an API.
|
||||||
|
/// Note that this is distinct from a value that is optional and not present!
|
||||||
|
///
|
||||||
|
/// Nullable implements many of the same methods as the Option type (map, unwrap, etc).
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||||
|
pub enum Nullable<T> {
|
||||||
|
/// Null value
|
||||||
|
Null,
|
||||||
|
/// Value is present
|
||||||
|
Present(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Nullable<T> {
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Querying the contained values
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Returns `true` if the Nullable is a `Present` value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x: Nullable<u32> = Nullable::Present(2);
|
||||||
|
/// assert_eq!(x.is_present(), true);
|
||||||
|
///
|
||||||
|
/// let x: Nullable<u32> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.is_present(), false);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn is_present(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Nullable::Present(_) => true,
|
||||||
|
Nullable::Null => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the Nullable is a `Null` value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x: Nullable<u32> = Nullable::Present(2);
|
||||||
|
/// assert_eq!(x.is_null(), false);
|
||||||
|
///
|
||||||
|
/// let x: Nullable<u32> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.is_null(), true);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn is_null(&self) -> bool {
|
||||||
|
!self.is_present()
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Adapter for working with references
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Converts from `Nullable<T>` to `Nullable<&T>`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Convert an `Nullable<`[`String`]`>` into a `Nullable<`[`usize`]`>`, preserving the original.
|
||||||
|
/// The [`map`] method takes the `self` argument by value, consuming the original,
|
||||||
|
/// so this technique uses `as_ref` to first take a `Nullable` to a reference
|
||||||
|
/// to the value inside the original.
|
||||||
|
///
|
||||||
|
/// [`map`]: enum.Nullable.html#method.map
|
||||||
|
/// [`String`]: ../../std/string/struct.String.html
|
||||||
|
/// [`usize`]: ../../std/primitive.usize.html
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let num_as_str: Nullable<String> = Nullable::Present("10".to_string());
|
||||||
|
/// // First, cast `Nullable<String>` to `Nullable<&String>` with `as_ref`,
|
||||||
|
/// // then consume *that* with `map`, leaving `num_as_str` on the stack.
|
||||||
|
/// let num_as_int: Nullable<usize> = num_as_str.as_ref().map(|n| n.len());
|
||||||
|
/// println!("still can print num_as_str: {:?}", num_as_str);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn as_ref(&self) -> Nullable<&T> {
|
||||||
|
match *self {
|
||||||
|
Nullable::Present(ref x) => Nullable::Present(x),
|
||||||
|
Nullable::Null => Nullable::Null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts from `Nullable<T>` to `Nullable<&mut T>`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let mut x = Nullable::Present(2);
|
||||||
|
/// match x.as_mut() {
|
||||||
|
/// Nullable::Present(v) => *v = 42,
|
||||||
|
/// Nullable::Null => {},
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(x, Nullable::Present(42));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn as_mut(&mut self) -> Nullable<&mut T> {
|
||||||
|
match *self {
|
||||||
|
Nullable::Present(ref mut x) => Nullable::Present(x),
|
||||||
|
Nullable::Null => Nullable::Null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getting to contained values
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Unwraps a Nullable, yielding the content of a `Nullable::Present`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the value is a [`Nullable::Null`] with a custom panic message provided by
|
||||||
|
/// `msg`.
|
||||||
|
///
|
||||||
|
/// [`Nullable::Null`]: #variant.Null
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present("value");
|
||||||
|
/// assert_eq!(x.expect("the world is ending"), "value");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x: Nullable<&str> = Nullable::Null;
|
||||||
|
/// x.expect("the world is ending"); // panics with `the world is ending`
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn expect(self, msg: &str) -> T {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(val) => val,
|
||||||
|
Nullable::Null => expect_failed(msg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Moves the value `v` out of the `Nullable<T>` if it is `Nullable::Present(v)`.
|
||||||
|
///
|
||||||
|
/// In general, because this function may panic, its use is discouraged.
|
||||||
|
/// Instead, prefer to use pattern matching and handle the `Nullable::Null`
|
||||||
|
/// case explicitly.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the self value equals [`Nullable::Null`].
|
||||||
|
///
|
||||||
|
/// [`Nullable::Null`]: #variant.Null
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present("air");
|
||||||
|
/// assert_eq!(x.unwrap(), "air");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x: Nullable<&str> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.unwrap(), "air"); // fails
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn unwrap(self) -> T {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(val) => val,
|
||||||
|
Nullable::Null => panic!("called `Nullable::unwrap()` on a `Nullable::Null` value"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the contained value or a default.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// assert_eq!(Nullable::Present("car").unwrap_or("bike"), "car");
|
||||||
|
/// assert_eq!(Nullable::Null.unwrap_or("bike"), "bike");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn unwrap_or(self, def: T) -> T {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(x) => x,
|
||||||
|
Nullable::Null => def,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the contained value or computes it from a closure.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let k = 10;
|
||||||
|
/// assert_eq!(Nullable::Present(4).unwrap_or_else(|| 2 * k), 4);
|
||||||
|
/// assert_eq!(Nullable::Null.unwrap_or_else(|| 2 * k), 20);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(x) => x,
|
||||||
|
Nullable::Null => f(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Transforming contained values
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Maps a `Nullable<T>` to `Nullable<U>` by applying a function to a contained value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Convert a `Nullable<`[`String`]`>` into a `Nullable<`[`usize`]`>`, consuming the original:
|
||||||
|
///
|
||||||
|
/// [`String`]: ../../std/string/struct.String.html
|
||||||
|
/// [`usize`]: ../../std/primitive.usize.html
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let maybe_some_string = Nullable::Present(String::from("Hello, World!"));
|
||||||
|
/// // `Nullable::map` takes self *by value*, consuming `maybe_some_string`
|
||||||
|
/// let maybe_some_len = maybe_some_string.map(|s| s.len());
|
||||||
|
///
|
||||||
|
/// assert_eq!(maybe_some_len, Nullable::Present(13));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Nullable<U> {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(x) => Nullable::Present(f(x)),
|
||||||
|
Nullable::Null => Nullable::Null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies a function to the contained value (if any),
|
||||||
|
/// or returns a `default` (if not).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present("foo");
|
||||||
|
/// assert_eq!(x.map_or(42, |v| v.len()), 3);
|
||||||
|
///
|
||||||
|
/// let x: Nullable<&str> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.map_or(42, |v| v.len()), 42);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(t) => f(t),
|
||||||
|
Nullable::Null => default,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies a function to the contained value (if any),
|
||||||
|
/// or computes a `default` (if not).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let k = 21;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present("foo");
|
||||||
|
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);
|
||||||
|
///
|
||||||
|
/// let x: Nullable<&str> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(t) => f(t),
|
||||||
|
Nullable::Null => default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transforms the `Nullable<T>` into a [`Result<T, E>`], mapping `Nullable::Present(v)` to
|
||||||
|
/// [`Ok(v)`] and `Nullable::Null` to [`Err(err)`][Err].
|
||||||
|
///
|
||||||
|
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
|
||||||
|
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
|
||||||
|
/// [Err]: ../../std/result/enum.Result.html#variant.Err
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present("foo");
|
||||||
|
/// assert_eq!(x.ok_or(0), Ok("foo"));
|
||||||
|
///
|
||||||
|
/// let x: Nullable<&str> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.ok_or(0), Err(0));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(v) => Ok(v),
|
||||||
|
Nullable::Null => Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transforms the `Nullable<T>` into a [`Result<T, E>`], mapping `Nullable::Present(v)` to
|
||||||
|
/// [`Ok(v)`] and `Nullable::Null` to [`Err(err())`][Err].
|
||||||
|
///
|
||||||
|
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
|
||||||
|
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
|
||||||
|
/// [Err]: ../../std/result/enum.Result.html#variant.Err
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present("foo");
|
||||||
|
/// assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
|
||||||
|
///
|
||||||
|
/// let x: Nullable<&str> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.ok_or_else(|| 0), Err(0));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(v) => Ok(v),
|
||||||
|
Nullable::Null => Err(err()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Boolean operations on the values, eager and lazy
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Returns `Nullable::Null` if the Nullable is `Nullable::Null`, otherwise returns `optb`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present(2);
|
||||||
|
/// let y: Nullable<&str> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.and(y), Nullable::Null);
|
||||||
|
///
|
||||||
|
/// let x: Nullable<u32> = Nullable::Null;
|
||||||
|
/// let y = Nullable::Present("foo");
|
||||||
|
/// assert_eq!(x.and(y), Nullable::Null);
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present(2);
|
||||||
|
/// let y = Nullable::Present("foo");
|
||||||
|
/// assert_eq!(x.and(y), Nullable::Present("foo"));
|
||||||
|
///
|
||||||
|
/// let x: Nullable<u32> = Nullable::Null;
|
||||||
|
/// let y: Nullable<&str> = Nullable::Null;
|
||||||
|
/// assert_eq!(x.and(y), Nullable::Null);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn and<U>(self, optb: Nullable<U>) -> Nullable<U> {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(_) => optb,
|
||||||
|
Nullable::Null => Nullable::Null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Nullable::Null` if the Nullable is `Nullable::Null`, otherwise calls `f` with the
|
||||||
|
/// wrapped value and returns the result.
|
||||||
|
///
|
||||||
|
/// Some languages call this operation flatmap.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// fn sq(x: u32) -> Nullable<u32> { Nullable::Present(x * x) }
|
||||||
|
/// fn nope(_: u32) -> Nullable<u32> { Nullable::Null }
|
||||||
|
///
|
||||||
|
/// assert_eq!(Nullable::Present(2).and_then(sq).and_then(sq), Nullable::Present(16));
|
||||||
|
/// assert_eq!(Nullable::Present(2).and_then(sq).and_then(nope), Nullable::Null);
|
||||||
|
/// assert_eq!(Nullable::Present(2).and_then(nope).and_then(sq), Nullable::Null);
|
||||||
|
/// assert_eq!(Nullable::Null.and_then(sq).and_then(sq), Nullable::Null);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn and_then<U, F: FnOnce(T) -> Nullable<U>>(self, f: F) -> Nullable<U> {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(x) => f(x),
|
||||||
|
Nullable::Null => Nullable::Null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Nullable if it contains a value, otherwise returns `optb`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present(2);
|
||||||
|
/// let y = Nullable::Null;
|
||||||
|
/// assert_eq!(x.or(y), Nullable::Present(2));
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Null;
|
||||||
|
/// let y = Nullable::Present(100);
|
||||||
|
/// assert_eq!(x.or(y), Nullable::Present(100));
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present(2);
|
||||||
|
/// let y = Nullable::Present(100);
|
||||||
|
/// assert_eq!(x.or(y), Nullable::Present(2));
|
||||||
|
///
|
||||||
|
/// let x: Nullable<u32> = Nullable::Null;
|
||||||
|
/// let y = Nullable::Null;
|
||||||
|
/// assert_eq!(x.or(y), Nullable::Null);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn or(self, optb: Nullable<T>) -> Nullable<T> {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(_) => self,
|
||||||
|
Nullable::Null => optb,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Nullable if it contains a value, otherwise calls `f` and
|
||||||
|
/// returns the result.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// fn nobody() -> Nullable<&'static str> { Nullable::Null }
|
||||||
|
/// fn vikings() -> Nullable<&'static str> { Nullable::Present("vikings") }
|
||||||
|
///
|
||||||
|
/// assert_eq!(Nullable::Present("barbarians").or_else(vikings),
|
||||||
|
/// Nullable::Present("barbarians"));
|
||||||
|
/// assert_eq!(Nullable::Null.or_else(vikings), Nullable::Present("vikings"));
|
||||||
|
/// assert_eq!(Nullable::Null.or_else(nobody), Nullable::Null);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn or_else<F: FnOnce() -> Nullable<T>>(self, f: F) -> Nullable<T> {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(_) => self,
|
||||||
|
Nullable::Null => f(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Misc
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Takes the value out of the Nullable, leaving a `Nullable::Null` in its place.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let mut x = Nullable::Present(2);
|
||||||
|
/// x.take();
|
||||||
|
/// assert_eq!(x, Nullable::Null);
|
||||||
|
///
|
||||||
|
/// let mut x: Nullable<u32> = Nullable::Null;
|
||||||
|
/// x.take();
|
||||||
|
/// assert_eq!(x, Nullable::Null);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn take(&mut self) -> Nullable<T> {
|
||||||
|
mem::replace(self, Nullable::Null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Nullable<&T> {
|
||||||
|
/// Maps an `Nullable<&T>` to an `Nullable<T>` by cloning the contents of the
|
||||||
|
/// Nullable.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = 12;
|
||||||
|
/// let opt_x = Nullable::Present(&x);
|
||||||
|
/// assert_eq!(opt_x, Nullable::Present(&12));
|
||||||
|
/// let cloned = opt_x.cloned();
|
||||||
|
/// assert_eq!(cloned, Nullable::Present(12));
|
||||||
|
/// ```
|
||||||
|
pub fn cloned(self) -> Nullable<T> {
|
||||||
|
self.map(Clone::clone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default> Nullable<T> {
|
||||||
|
/// Returns the contained value or a default
|
||||||
|
///
|
||||||
|
/// Consumes the `self` argument then, if `Nullable::Present`, returns the contained
|
||||||
|
/// value, otherwise if `Nullable::Null`, returns the default value for that
|
||||||
|
/// type.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use apikey_auths::types::Nullable;
|
||||||
|
///
|
||||||
|
/// let x = Nullable::Present(42);
|
||||||
|
/// assert_eq!(42, x.unwrap_or_default());
|
||||||
|
///
|
||||||
|
/// let y: Nullable<i32> = Nullable::Null;
|
||||||
|
/// assert_eq!(0, y.unwrap_or_default());
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn unwrap_or_default(self) -> T {
|
||||||
|
match self {
|
||||||
|
Nullable::Present(x) => x,
|
||||||
|
Nullable::Null => Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Nullable<T> {
|
||||||
|
/// Returns None.
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Nullable<T> {
|
||||||
|
Nullable::Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for Nullable<T> {
|
||||||
|
fn from(val: T) -> Nullable<T> {
|
||||||
|
Nullable::Present(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Serialize for Nullable<T>
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match *self {
|
||||||
|
Nullable::Present(ref inner) => serializer.serialize_some(&inner),
|
||||||
|
Nullable::Null => serializer.serialize_none(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, T> Deserialize<'de> for Nullable<T>
|
||||||
|
where
|
||||||
|
T: serde::de::DeserializeOwned,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Nullable<T>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
// In order to deserialize a required, but nullable, value, we first have to check whether
|
||||||
|
// the value is present at all. To do this, we deserialize to a serde_json::Value, which
|
||||||
|
// fails if the value is missing, or gives serde_json::Value::Null if the value is present.
|
||||||
|
// If that succeeds as null, we can easily return a Null.
|
||||||
|
// If that succeeds as some value, we deserialize that value and return a Present.
|
||||||
|
// If that errors, we return the error.
|
||||||
|
let presence: Result<::serde_json::Value, _> =
|
||||||
|
serde::Deserialize::deserialize(deserializer);
|
||||||
|
match presence {
|
||||||
|
Ok(serde_json::Value::Null) => Ok(Nullable::Null),
|
||||||
|
Ok(some_value) => serde_json::from_value(some_value)
|
||||||
|
.map(Nullable::Present)
|
||||||
|
.map_err(serde::de::Error::custom),
|
||||||
|
Err(x) => Err(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
#[cold]
|
||||||
|
fn expect_failed(msg: &str) -> ! {
|
||||||
|
panic!("{}", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||||
|
/// Base64-encoded byte array
|
||||||
|
pub struct ByteArray(pub Vec<u8>);
|
||||||
|
|
||||||
|
impl Serialize for ByteArray {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&general_purpose::STANDARD.encode(&self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for ByteArray {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<ByteArray, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s = String::deserialize(deserializer)?;
|
||||||
|
match general_purpose::STANDARD.decode(s) {
|
||||||
|
Ok(bin) => Ok(ByteArray(bin)),
|
||||||
|
_ => Err(serde::de::Error::custom("invalid base64")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -602,7 +602,7 @@ where
|
|||||||
{
|
{
|
||||||
// Header parameters
|
// Header parameters
|
||||||
let header_params = {
|
let header_params = {
|
||||||
let header_x_header = headers.get(HeaderName::from_static("x_header"));
|
let header_x_header = headers.get(HeaderName::from_static("X-Header"));
|
||||||
|
|
||||||
let header_x_header = match header_x_header {
|
let header_x_header = match header_x_header {
|
||||||
Some(v) => match header::IntoHeaderValue::<String>::try_from((*v).clone()) {
|
Some(v) => match header::IntoHeaderValue::<String>::try_from((*v).clone()) {
|
||||||
@ -1471,7 +1471,7 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), success_info);
|
response_headers.insert(HeaderName::from_static("Success-Info"), success_info);
|
||||||
}
|
}
|
||||||
if let Some(bool_header) = bool_header {
|
if let Some(bool_header) = bool_header {
|
||||||
let bool_header = match header::IntoHeaderValue(bool_header).try_into() {
|
let bool_header = match header::IntoHeaderValue(bool_header).try_into() {
|
||||||
@ -1485,7 +1485,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), bool_header);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("Bool-Header"), bool_header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(object_header) = object_header {
|
if let Some(object_header) = object_header {
|
||||||
@ -1500,7 +1501,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), object_header);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("Object-Header"), object_header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut response = response.status(200);
|
let mut response = response.status(200);
|
||||||
@ -1541,7 +1543,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), further_info);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("Further-Info"), further_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(failure_info) = failure_info {
|
if let Some(failure_info) = failure_info {
|
||||||
@ -1556,7 +1559,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), failure_info);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("Failure-Info"), failure_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut response = response.status(412);
|
let mut response = response.status(412);
|
||||||
@ -1706,7 +1710,7 @@ where
|
|||||||
{
|
{
|
||||||
// Header parameters
|
// Header parameters
|
||||||
let header_params = {
|
let header_params = {
|
||||||
let header_x_header_one = headers.get(HeaderName::from_static("x_header_one"));
|
let header_x_header_one = headers.get(HeaderName::from_static("x-header-one"));
|
||||||
|
|
||||||
let header_x_header_one = match header_x_header_one {
|
let header_x_header_one = match header_x_header_one {
|
||||||
Some(v) => match header::IntoHeaderValue::<bool>::try_from((*v).clone()) {
|
Some(v) => match header::IntoHeaderValue::<bool>::try_from((*v).clone()) {
|
||||||
@ -1723,7 +1727,7 @@ where
|
|||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let header_x_header_two = headers.get(HeaderName::from_static("x_header_two"));
|
let header_x_header_two = headers.get(HeaderName::from_static("x-header-two"));
|
||||||
|
|
||||||
let header_x_header_two = match header_x_header_two {
|
let header_x_header_two = match header_x_header_two {
|
||||||
Some(v) => match header::IntoHeaderValue::<bool>::try_from((*v).clone()) {
|
Some(v) => match header::IntoHeaderValue::<bool>::try_from((*v).clone()) {
|
||||||
|
@ -4,3 +4,12 @@ pub mod fake_classname_tags123;
|
|||||||
pub mod pet;
|
pub mod pet;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
||||||
|
/// API Key Authentication - Header.
|
||||||
|
pub trait ApiKeyAuthHeader {
|
||||||
|
fn extract_token_from_header(
|
||||||
|
&self,
|
||||||
|
headers: &axum::http::header::HeaderMap,
|
||||||
|
key: &str,
|
||||||
|
) -> Option<String>;
|
||||||
|
}
|
||||||
|
@ -140,6 +140,7 @@ pub trait Pet {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
path_params: models::GetPetByIdPathParams,
|
path_params: models::GetPetByIdPathParams,
|
||||||
) -> Result<GetPetByIdResponse, String>;
|
) -> Result<GetPetByIdResponse, String>;
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ pub trait Store {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
) -> Result<GetInventoryResponse, String>;
|
) -> Result<GetInventoryResponse, String>;
|
||||||
|
|
||||||
/// Find purchase order by ID.
|
/// Find purchase order by ID.
|
||||||
|
@ -22,6 +22,7 @@ where
|
|||||||
+ apis::pet::Pet
|
+ apis::pet::Pet
|
||||||
+ apis::store::Store
|
+ apis::store::Store
|
||||||
+ apis::user::User
|
+ apis::user::User
|
||||||
|
+ apis::ApiKeyAuthHeader
|
||||||
+ 'static,
|
+ 'static,
|
||||||
{
|
{
|
||||||
// build our application with a route
|
// build our application with a route
|
||||||
@ -1646,13 +1647,25 @@ async fn get_pet_by_id<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
Path(path_params): Path<models::GetPetByIdPathParams>,
|
Path(path_params): Path<models::GetPetByIdPathParams>,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::pet::Pet,
|
A: apis::pet::Pet + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || get_pet_by_id_validation(path_params))
|
let validation = tokio::task::spawn_blocking(move || get_pet_by_id_validation(path_params))
|
||||||
.await
|
.await
|
||||||
@ -1667,7 +1680,7 @@ where
|
|||||||
|
|
||||||
let result = api_impl
|
let result = api_impl
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.get_pet_by_id(method, host, cookies, path_params)
|
.get_pet_by_id(method, host, cookies, token_in_header, path_params)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
@ -2022,12 +2035,24 @@ async fn get_inventory<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::store::Store,
|
A: apis::store::Store + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || get_inventory_validation())
|
let validation = tokio::task::spawn_blocking(move || get_inventory_validation())
|
||||||
.await
|
.await
|
||||||
@ -2040,7 +2065,10 @@ where
|
|||||||
.map_err(|_| StatusCode::BAD_REQUEST);
|
.map_err(|_| StatusCode::BAD_REQUEST);
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = api_impl.as_ref().get_inventory(method, host, cookies).await;
|
let result = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.get_inventory(method, host, cookies, token_in_header)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
|
|
||||||
@ -2656,7 +2684,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), x_rate_limit);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("X-Rate-Limit"), x_rate_limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(x_expires_after) = x_expires_after {
|
if let Some(x_expires_after) = x_expires_after {
|
||||||
@ -2672,7 +2701,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), x_expires_after);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("X-Expires-After"), x_expires_after);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut response = response.status(200);
|
let mut response = response.status(200);
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
pub mod pet;
|
pub mod pet;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
||||||
|
/// API Key Authentication - Header.
|
||||||
|
pub trait ApiKeyAuthHeader {
|
||||||
|
fn extract_token_from_header(
|
||||||
|
&self,
|
||||||
|
headers: &axum::http::header::HeaderMap,
|
||||||
|
key: &str,
|
||||||
|
) -> Option<String>;
|
||||||
|
}
|
||||||
|
@ -144,6 +144,7 @@ pub trait Pet {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
path_params: models::GetPetByIdPathParams,
|
path_params: models::GetPetByIdPathParams,
|
||||||
) -> Result<GetPetByIdResponse, String>;
|
) -> Result<GetPetByIdResponse, String>;
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ pub trait Store {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
) -> Result<GetInventoryResponse, String>;
|
) -> Result<GetInventoryResponse, String>;
|
||||||
|
|
||||||
/// Find purchase order by ID.
|
/// Find purchase order by ID.
|
||||||
|
@ -98,6 +98,7 @@ pub trait User {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
body: models::User,
|
body: models::User,
|
||||||
) -> Result<CreateUserResponse, String>;
|
) -> Result<CreateUserResponse, String>;
|
||||||
|
|
||||||
@ -109,6 +110,7 @@ pub trait User {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
body: Vec<models::User>,
|
body: Vec<models::User>,
|
||||||
) -> Result<CreateUsersWithArrayInputResponse, String>;
|
) -> Result<CreateUsersWithArrayInputResponse, String>;
|
||||||
|
|
||||||
@ -120,6 +122,7 @@ pub trait User {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
body: Vec<models::User>,
|
body: Vec<models::User>,
|
||||||
) -> Result<CreateUsersWithListInputResponse, String>;
|
) -> Result<CreateUsersWithListInputResponse, String>;
|
||||||
|
|
||||||
@ -131,6 +134,7 @@ pub trait User {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
path_params: models::DeleteUserPathParams,
|
path_params: models::DeleteUserPathParams,
|
||||||
) -> Result<DeleteUserResponse, String>;
|
) -> Result<DeleteUserResponse, String>;
|
||||||
|
|
||||||
@ -164,6 +168,7 @@ pub trait User {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
) -> Result<LogoutUserResponse, String>;
|
) -> Result<LogoutUserResponse, String>;
|
||||||
|
|
||||||
/// Updated user.
|
/// Updated user.
|
||||||
@ -174,6 +179,7 @@ pub trait User {
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
token_in_header: Option<String>,
|
||||||
path_params: models::UpdateUserPathParams,
|
path_params: models::UpdateUserPathParams,
|
||||||
body: models::User,
|
body: models::User,
|
||||||
) -> Result<UpdateUserResponse, String>;
|
) -> Result<UpdateUserResponse, String>;
|
||||||
|
@ -16,7 +16,7 @@ use crate::{apis, models};
|
|||||||
pub fn new<I, A>(api_impl: I) -> Router
|
pub fn new<I, A>(api_impl: I) -> Router
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Clone + Send + Sync + 'static,
|
I: AsRef<A> + Clone + Send + Sync + 'static,
|
||||||
A: apis::pet::Pet + apis::store::Store + apis::user::User + 'static,
|
A: apis::pet::Pet + apis::store::Store + apis::user::User + apis::ApiKeyAuthHeader + 'static,
|
||||||
{
|
{
|
||||||
// build our application with a route
|
// build our application with a route
|
||||||
Router::new()
|
Router::new()
|
||||||
@ -395,13 +395,25 @@ async fn get_pet_by_id<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
Path(path_params): Path<models::GetPetByIdPathParams>,
|
Path(path_params): Path<models::GetPetByIdPathParams>,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::pet::Pet,
|
A: apis::pet::Pet + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || get_pet_by_id_validation(path_params))
|
let validation = tokio::task::spawn_blocking(move || get_pet_by_id_validation(path_params))
|
||||||
.await
|
.await
|
||||||
@ -416,7 +428,7 @@ where
|
|||||||
|
|
||||||
let result = api_impl
|
let result = api_impl
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.get_pet_by_id(method, host, cookies, path_params)
|
.get_pet_by_id(method, host, cookies, token_in_header, path_params)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
@ -787,12 +799,24 @@ async fn get_inventory<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::store::Store,
|
A: apis::store::Store + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || get_inventory_validation())
|
let validation = tokio::task::spawn_blocking(move || get_inventory_validation())
|
||||||
.await
|
.await
|
||||||
@ -805,7 +829,10 @@ where
|
|||||||
.map_err(|_| StatusCode::BAD_REQUEST);
|
.map_err(|_| StatusCode::BAD_REQUEST);
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = api_impl.as_ref().get_inventory(method, host, cookies).await;
|
let result = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.get_inventory(method, host, cookies, token_in_header)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
|
|
||||||
@ -1034,13 +1061,25 @@ async fn create_user<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
Json(body): Json<models::User>,
|
Json(body): Json<models::User>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::user::User,
|
A: apis::user::User + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || create_user_validation(body))
|
let validation = tokio::task::spawn_blocking(move || create_user_validation(body))
|
||||||
.await
|
.await
|
||||||
@ -1055,7 +1094,7 @@ where
|
|||||||
|
|
||||||
let result = api_impl
|
let result = api_impl
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.create_user(method, host, cookies, body)
|
.create_user(method, host, cookies, token_in_header, body)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
@ -1102,13 +1141,25 @@ async fn create_users_with_array_input<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
Json(body): Json<Vec<models::User>>,
|
Json(body): Json<Vec<models::User>>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::user::User,
|
A: apis::user::User + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation =
|
let validation =
|
||||||
tokio::task::spawn_blocking(move || create_users_with_array_input_validation(body))
|
tokio::task::spawn_blocking(move || create_users_with_array_input_validation(body))
|
||||||
@ -1124,7 +1175,7 @@ where
|
|||||||
|
|
||||||
let result = api_impl
|
let result = api_impl
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.create_users_with_array_input(method, host, cookies, body)
|
.create_users_with_array_input(method, host, cookies, token_in_header, body)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
@ -1171,13 +1222,25 @@ async fn create_users_with_list_input<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
Json(body): Json<Vec<models::User>>,
|
Json(body): Json<Vec<models::User>>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::user::User,
|
A: apis::user::User + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation =
|
let validation =
|
||||||
tokio::task::spawn_blocking(move || create_users_with_list_input_validation(body))
|
tokio::task::spawn_blocking(move || create_users_with_list_input_validation(body))
|
||||||
@ -1193,7 +1256,7 @@ where
|
|||||||
|
|
||||||
let result = api_impl
|
let result = api_impl
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.create_users_with_list_input(method, host, cookies, body)
|
.create_users_with_list_input(method, host, cookies, token_in_header, body)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
@ -1232,13 +1295,25 @@ async fn delete_user<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
Path(path_params): Path<models::DeleteUserPathParams>,
|
Path(path_params): Path<models::DeleteUserPathParams>,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::user::User,
|
A: apis::user::User + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || delete_user_validation(path_params))
|
let validation = tokio::task::spawn_blocking(move || delete_user_validation(path_params))
|
||||||
.await
|
.await
|
||||||
@ -1253,7 +1328,7 @@ where
|
|||||||
|
|
||||||
let result = api_impl
|
let result = api_impl
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.delete_user(method, host, cookies, path_params)
|
.delete_user(method, host, cookies, token_in_header, path_params)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
@ -1422,7 +1497,7 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), set_cookie);
|
response_headers.insert(HeaderName::from_static("Set-Cookie"), set_cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(x_rate_limit) = x_rate_limit {
|
if let Some(x_rate_limit) = x_rate_limit {
|
||||||
@ -1437,7 +1512,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), x_rate_limit);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("X-Rate-Limit"), x_rate_limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(x_expires_after) = x_expires_after {
|
if let Some(x_expires_after) = x_expires_after {
|
||||||
@ -1453,7 +1529,8 @@ where
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut response_headers = response.headers_mut().unwrap();
|
let mut response_headers = response.headers_mut().unwrap();
|
||||||
response_headers.insert(HeaderName::from_static(""), x_expires_after);
|
response_headers
|
||||||
|
.insert(HeaderName::from_static("X-Expires-After"), x_expires_after);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut response = response.status(200);
|
let mut response = response.status(200);
|
||||||
@ -1499,12 +1576,24 @@ async fn logout_user<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::user::User,
|
A: apis::user::User + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || logout_user_validation())
|
let validation = tokio::task::spawn_blocking(move || logout_user_validation())
|
||||||
.await
|
.await
|
||||||
@ -1517,7 +1606,10 @@ where
|
|||||||
.map_err(|_| StatusCode::BAD_REQUEST);
|
.map_err(|_| StatusCode::BAD_REQUEST);
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = api_impl.as_ref().logout_user(method, host, cookies).await;
|
let result = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.logout_user(method, host, cookies, token_in_header)
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
|
|
||||||
@ -1565,14 +1657,26 @@ async fn update_user<I, A>(
|
|||||||
method: Method,
|
method: Method,
|
||||||
host: Host,
|
host: Host,
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
Path(path_params): Path<models::UpdateUserPathParams>,
|
Path(path_params): Path<models::UpdateUserPathParams>,
|
||||||
State(api_impl): State<I>,
|
State(api_impl): State<I>,
|
||||||
Json(body): Json<models::User>,
|
Json(body): Json<models::User>,
|
||||||
) -> Result<Response, StatusCode>
|
) -> Result<Response, StatusCode>
|
||||||
where
|
where
|
||||||
I: AsRef<A> + Send + Sync,
|
I: AsRef<A> + Send + Sync,
|
||||||
A: apis::user::User,
|
A: apis::user::User + apis::ApiKeyAuthHeader,
|
||||||
{
|
{
|
||||||
|
// Authentication
|
||||||
|
let token_in_header = api_impl
|
||||||
|
.as_ref()
|
||||||
|
.extract_token_from_header(&headers, "ApiKey");
|
||||||
|
if let (None,) = (&token_in_header,) {
|
||||||
|
return Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(Body::empty())
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
let validation = tokio::task::spawn_blocking(move || update_user_validation(path_params, body))
|
let validation = tokio::task::spawn_blocking(move || update_user_validation(path_params, body))
|
||||||
.await
|
.await
|
||||||
@ -1587,7 +1691,7 @@ where
|
|||||||
|
|
||||||
let result = api_impl
|
let result = api_impl
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.update_user(method, host, cookies, path_params, body)
|
.update_user(method, host, cookies, token_in_header, path_params, body)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut response = Response::builder();
|
let mut response = Response::builder();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user