mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-11-19 01:53:41 +00:00
[Rust-Axum] Basic Authorization - Basic Analytic - XSS Sanitize (#21578)
* Update * Update * Update * Update * Update * Update
This commit is contained in:
parent
0b0d534d0d
commit
777b7eeea0
14
bin/configs/manual/rust-axum-apikey-authorization.yaml
Normal file
14
bin/configs/manual/rust-axum-apikey-authorization.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
generatorName: rust-axum
|
||||
outputDir: samples/server/petstore/rust-axum/output/apikey-authorization
|
||||
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-authorization
|
||||
basicAuthorization: true
|
||||
basicAnalytic: true
|
||||
ownedRequest: true
|
||||
globalProperties:
|
||||
skipFormModel: false
|
||||
enablePostProcessFile: true
|
||||
@ -61,6 +61,9 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
||||
private Boolean allowBlockingValidator = false;
|
||||
private Boolean allowBlockingResponseSerialize = false;
|
||||
private String externCrateName;
|
||||
private Boolean basicAuthorization = false;
|
||||
private Boolean basicAnalytic = false;
|
||||
private Boolean ownedRequest = false;
|
||||
|
||||
// Types
|
||||
private static final String uuidType = "uuid::Uuid";
|
||||
@ -286,7 +289,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
||||
LOGGER.info("Warning: Environment variable 'RUST_POST_PROCESS_FILE' is set but file post-processing is not enabled. To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
if (!Boolean.TRUE.equals(ModelUtils.isGenerateAliasAsModel())) {
|
||||
if (!ModelUtils.isGenerateAliasAsModel()) {
|
||||
LOGGER.warn("generateAliasAsModel is set to false, which means array/map will be generated as model instead and the resulting code may have issues. Please enable `generateAliasAsModel` to address the issue.");
|
||||
}
|
||||
|
||||
@ -316,6 +319,24 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
||||
} else {
|
||||
additionalProperties.put("allowBlockingResponseSerialize", allowBlockingResponseSerialize);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey("basicAuthorization")) {
|
||||
basicAuthorization = convertPropertyToBooleanAndWriteBack("basicAuthorization");
|
||||
} else {
|
||||
additionalProperties.put("basicAuthorization", basicAuthorization);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey("basicAnalytic")) {
|
||||
basicAnalytic = convertPropertyToBooleanAndWriteBack("basicAnalytic");
|
||||
} else {
|
||||
additionalProperties.put("basicAnalytic", basicAnalytic);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey("ownedRequest")) {
|
||||
ownedRequest = convertPropertyToBooleanAndWriteBack("ownedRequest");
|
||||
} else {
|
||||
additionalProperties.put("ownedRequest", ownedRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPackageName(String packageName) {
|
||||
@ -722,6 +743,21 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
||||
operations.put("havingAuthMethod", true);
|
||||
operations.getOperation().forEach(op -> op.vendorExtensions.put("havingAuthMethod", true));
|
||||
this.havingAuthMethods = true;
|
||||
|
||||
if (basicAuthorization) {
|
||||
operations.put("basicAuthorization", true);
|
||||
operations.getOperation().forEach(op -> op.vendorExtensions.put("basicAuthorization", true));
|
||||
}
|
||||
}
|
||||
|
||||
if (basicAnalytic) {
|
||||
operations.put("basicAnalytic", true);
|
||||
operations.getOperation().forEach(op -> op.vendorExtensions.put("basicAnalytic", true));
|
||||
}
|
||||
|
||||
if (ownedRequest) {
|
||||
operations.put("ownedRequest", true);
|
||||
operations.getOperation().forEach(op -> op.vendorExtensions.put("ownedRequest", true));
|
||||
}
|
||||
|
||||
return operationsMap;
|
||||
@ -982,6 +1018,22 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
|
||||
property.dataType = objectType;
|
||||
property.isNullable = false;
|
||||
}
|
||||
|
||||
if (property.dataType.startsWith(vecType + "<String")) {
|
||||
property.vendorExtensions.put("is-vec-string", true);
|
||||
} else if (property.dataType.startsWith(vecType + "<models::")) {
|
||||
property.vendorExtensions.put("is-vec-nested", true);
|
||||
} else if (property.dataType.startsWith(mapType + "<String, String")) {
|
||||
property.vendorExtensions.put("is-map-string", true);
|
||||
} else if (property.dataType.startsWith(mapType + "<String, models::")) {
|
||||
property.vendorExtensions.put("is-map-nested", true);
|
||||
} else if (property.dataType.startsWith(mapType + "<String")) {
|
||||
property.vendorExtensions.put("is-map", true);
|
||||
} else if (property.dataType.startsWith("models::")) {
|
||||
property.vendorExtensions.put("is-nested", true);
|
||||
} else if (stringType.equals(property.dataType)) {
|
||||
property.vendorExtensions.put("is-string", true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -13,7 +13,7 @@ description = "{{{.}}}"
|
||||
{{#licenseInfo}}
|
||||
license = "{{.}}"
|
||||
{{/licenseInfo}}
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
{{#publishRustRegistry}}
|
||||
publish = ["{{.}}"]
|
||||
{{/publishRustRegistry}}
|
||||
@ -39,6 +39,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -4,6 +4,39 @@ pub mod {{classFilename}};
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
|
||||
{{#basicAuthorization}}
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Authorization {
|
||||
Authorized,
|
||||
Forbidden,
|
||||
}
|
||||
{{/basicAuthorization}}
|
||||
|
||||
{{#basicAnalytic}}
|
||||
pub mod event {
|
||||
/// Anything to be recorded.
|
||||
pub type Event = std::collections::HashMap<String, String>;
|
||||
|
||||
pub mod convention {
|
||||
pub const EVENT_SERVICE: &str = "_service_";
|
||||
pub const EVENT_ACTOR: &str = "_actor_";
|
||||
pub const EVENT_ACTION: &str = "_action_";
|
||||
pub const EVENT_RESOURCE_TYPE: &str = "_resource_type_";
|
||||
pub const EVENT_RESOURCE: &str = "_resource_";
|
||||
pub const EVENT_STATUS_CODE: &str = "_status_code_";
|
||||
pub const EVENT_LATENCY_SECS: &str = "_latency_secs_";
|
||||
pub const EVENT_TIMESTAMP: &str = "timestamp";
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait EventDispatcher {
|
||||
fn service_name(&self) -> String;
|
||||
async fn dispatch(&self, event: event::Event) {}
|
||||
}
|
||||
{{/basicAnalytic}}
|
||||
|
||||
{{#authMethods}}
|
||||
{{#isApiKey}}
|
||||
{{#isKeyInCookie}}
|
||||
|
||||
@ -15,6 +15,75 @@ use crate::{models, types::*};
|
||||
{{/operations}}
|
||||
|
||||
{{#operations}}
|
||||
|
||||
{{#basicAuthorization}}
|
||||
/// {{classnamePascalCase}} APIs - Authorization.
|
||||
#[async_trait]
|
||||
#[allow(clippy::ptr_arg)]
|
||||
pub trait {{classnamePascalCase}}Authorization {
|
||||
type Claims;
|
||||
|
||||
{{#operation}}
|
||||
{{#vendorExtensions}}
|
||||
{{#x-has-auth-methods}}
|
||||
{{#basicAuthorization}}
|
||||
{{#vendorExtensions}}
|
||||
/// Authorization{{#summary}} - {{{.}}}{{/summary}}.
|
||||
/// {{{operationId}}} - {{{httpMethod}}} {{{basePathWithoutHost}}}{{{path}}}
|
||||
async fn {{{x-operation-id}}}_authorize(
|
||||
&self,
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
claims: &Self::Claims,
|
||||
{{#headerParams.size}}
|
||||
header_params: &models::{{{operationIdCamelCase}}}HeaderParams,
|
||||
{{/headerParams.size}}
|
||||
{{#pathParams.size}}
|
||||
path_params: &models::{{{operationIdCamelCase}}}PathParams,
|
||||
{{/pathParams.size}}
|
||||
{{#queryParams.size}}
|
||||
query_params: &models::{{{operationIdCamelCase}}}QueryParams,
|
||||
{{/queryParams.size}}
|
||||
{{^x-consumes-multipart-related}}
|
||||
{{^x-consumes-multipart}}
|
||||
{{#bodyParam}}
|
||||
{{#vendorExtensions}}
|
||||
{{^x-consumes-plain-text}}
|
||||
body: &{{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}},
|
||||
{{/x-consumes-plain-text}}
|
||||
{{#x-consumes-plain-text}}
|
||||
{{#isString}}
|
||||
body: &String,
|
||||
{{/isString}}
|
||||
{{^isString}}
|
||||
body: &Bytes,
|
||||
{{/isString}}
|
||||
{{/x-consumes-plain-text}}
|
||||
{{/vendorExtensions}}
|
||||
{{/bodyParam}}
|
||||
{{/x-consumes-multipart}}
|
||||
{{/x-consumes-multipart-related}}
|
||||
{{#x-consumes-multipart}}
|
||||
body: &Multipart,
|
||||
{{/x-consumes-multipart}}
|
||||
{{#x-consumes-multipart-related}}
|
||||
body: &axum::body::Body,
|
||||
{{/x-consumes-multipart-related}}
|
||||
) -> Result<super::Authorization, ()> {
|
||||
Ok(super::Authorization::Authorized)
|
||||
}
|
||||
{{/vendorExtensions}}
|
||||
{{/basicAuthorization}}
|
||||
{{/x-has-auth-methods}}
|
||||
{{/vendorExtensions}}
|
||||
{{^-last}}
|
||||
|
||||
{{/-last}}
|
||||
{{/operation}}
|
||||
}
|
||||
{{/basicAuthorization}}
|
||||
|
||||
/// {{classnamePascalCase}}
|
||||
#[async_trait]
|
||||
#[allow(clippy::ptr_arg)]
|
||||
@ -32,36 +101,37 @@ pub trait {{classnamePascalCase}}<E: std::fmt::Debug + Send + Sync + 'static = (
|
||||
/// {{{operationId}}} - {{{httpMethod}}} {{{basePathWithoutHost}}}{{{path}}}
|
||||
async fn {{{x-operation-id}}}(
|
||||
&self,
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
{{#basicAnalytic}}event: &mut super::event::Event,{{/basicAnalytic}}
|
||||
method: {{^ownedRequest}}&{{/ownedRequest}}Method,
|
||||
host: {{^ownedRequest}}&{{/ownedRequest}}Host,
|
||||
cookies: {{^ownedRequest}}&{{/ownedRequest}}CookieJar,
|
||||
{{#vendorExtensions}}
|
||||
{{#x-has-auth-methods}}
|
||||
claims: &Self::Claims,
|
||||
claims: {{^ownedRequest}}&{{/ownedRequest}}Self::Claims,
|
||||
{{/x-has-auth-methods}}
|
||||
{{/vendorExtensions}}
|
||||
{{#headerParams.size}}
|
||||
header_params: &models::{{{operationIdCamelCase}}}HeaderParams,
|
||||
header_params: {{^ownedRequest}}&{{/ownedRequest}}models::{{{operationIdCamelCase}}}HeaderParams,
|
||||
{{/headerParams.size}}
|
||||
{{#pathParams.size}}
|
||||
path_params: &models::{{{operationIdCamelCase}}}PathParams,
|
||||
path_params: {{^ownedRequest}}&{{/ownedRequest}}models::{{{operationIdCamelCase}}}PathParams,
|
||||
{{/pathParams.size}}
|
||||
{{#queryParams.size}}
|
||||
query_params: &models::{{{operationIdCamelCase}}}QueryParams,
|
||||
query_params: {{^ownedRequest}}&{{/ownedRequest}}models::{{{operationIdCamelCase}}}QueryParams,
|
||||
{{/queryParams.size}}
|
||||
{{^x-consumes-multipart-related}}
|
||||
{{^x-consumes-multipart}}
|
||||
{{#bodyParam}}
|
||||
{{#vendorExtensions}}
|
||||
{{^x-consumes-plain-text}}
|
||||
body: &{{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}},
|
||||
body: {{^ownedRequest}}&{{/ownedRequest}}{{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}},
|
||||
{{/x-consumes-plain-text}}
|
||||
{{#x-consumes-plain-text}}
|
||||
{{#isString}}
|
||||
body: &String,
|
||||
body: {{^ownedRequest}}&{{/ownedRequest}}String,
|
||||
{{/isString}}
|
||||
{{^isString}}
|
||||
body: &Bytes,
|
||||
body: {{^ownedRequest}}&{{/ownedRequest}}Bytes,
|
||||
{{/isString}}
|
||||
{{/x-consumes-plain-text}}
|
||||
{{/vendorExtensions}}
|
||||
|
||||
@ -30,11 +30,10 @@ macro_rules! ihv_generate {
|
||||
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!(r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t))),
|
||||
},
|
||||
Err(e) => Err(format!("Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e)),
|
||||
Err(e) => Err(format!(r#"Unable to parse header {hdr_value:?} as a string - {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,8 +74,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
y => Some(y.to_string()),
|
||||
})
|
||||
.collect())),
|
||||
Err(e) => Err(format!("Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e)),
|
||||
Err(e) => Err(format!(r#"Unable to parse header: {hdr_value:?} as a string - {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,8 +85,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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))
|
||||
Err(e) => Err(format!(r#"Unable to convert {hdr_value:?} into a header - {e}"#))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,10 +98,9 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
@ -113,8 +109,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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))
|
||||
Err(e) => Err(format!(r#"Unable to convert {hdr_value:?} from a header {e}"#))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,11 +123,9 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!("Unable to convert {:?} from a header {}",
|
||||
hdr_value, e)),
|
||||
Err(e) => Err(format!(r#"Unable to convert {hdr_value:?} from a header {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,9 +136,8 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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))
|
||||
}
|
||||
Err(e) => Err(format!(r#"Unable to convert: {hdr_value:?} into a header: {e}"#))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,11 +150,9 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!("Unable to convert header {:?} to string {}",
|
||||
hdr_value, e)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to string {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -173,8 +163,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert {hdr_value:?} to a header: {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,12 +178,9 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<uuid::Uuid> {
|
||||
match hdr_value.to_str() {
|
||||
Ok(hdr_value) => match uuid::Uuid::from_str(hdr_value) {
|
||||
Ok(uuid) => Ok(IntoHeaderValue(uuid)),
|
||||
Err(e) => Err(format!("Unable to parse: {} as uuid - {}", hdr_value, e)),
|
||||
Err(e) => Err(format!(r#"Unable to parse: {hdr_value} as uuid - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to string {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,10 +191,7 @@ impl TryFrom<IntoHeaderValue<uuid::Uuid>> for HeaderValue {
|
||||
fn try_from(hdr_value: IntoHeaderValue<uuid::Uuid>) -> Result<Self, Self::Error> {
|
||||
match HeaderValue::from_bytes(hdr_value.0.as_bytes()) {
|
||||
Ok(hdr_value) => Ok(hdr_value),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} to a header: {}",
|
||||
hdr_value, e
|
||||
)),
|
||||
Err(e) => Err(format!(r#"Unable to convert {hdr_value:?} to a header: {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,12 +7,64 @@ use validator::Validate;
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(v: &std::collections::HashMap<String, T>) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
{{! Don't "use" structs here - they can conflict with the names of models, and mean that the code won't compile }}
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
|
||||
|
||||
{{#vendorExtensions}}
|
||||
{{#headerParams.size}}
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
@ -68,10 +120,54 @@ use crate::{models, types::*};
|
||||
length(min = {{minItems}}),
|
||||
{{/minItems}}
|
||||
{{/maxItems}}
|
||||
)]
|
||||
{{#vendorExtensions.is-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
custom(function = "check_xss_string")),
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
custom(function = "check_xss_vec_string"),
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
custom(function = "check_xss_map_nested"),
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
custom(function = "check_xss_map"),
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
custom(function = "check_xss_map_string"),
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
)]
|
||||
{{/hasValidation}}
|
||||
{{^hasValidation}}
|
||||
{{#vendorExtensions.is-nested}}
|
||||
#[validate(nested)]
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
#[validate(nested)
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
#[validate(custom(function = "check_xss_vec_string"))]
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
#[validate(custom(function = "check_xss_map_nested"))]
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
#[validate(custom(function = "check_xss_map"))]
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
#[validate(custom(function = "check_xss_map_string"))]
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
{{/hasValidation}}
|
||||
pub {{{paramName}}}: {{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}},
|
||||
{{/headerParams}}
|
||||
{{/headerParams}}
|
||||
}
|
||||
|
||||
{{#headerParams}}
|
||||
@ -97,15 +193,15 @@ use crate::{models, types::*};
|
||||
{{/isByteArray}}
|
||||
{{/pattern}}
|
||||
{{/hasValidation}}
|
||||
{{/headerParams}}
|
||||
|
||||
{{/headerParams}}
|
||||
|
||||
{{/headerParams.size}}
|
||||
{{#pathParams.size}}
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct {{{operationIdCamelCase}}}PathParams {
|
||||
{{#pathParams}}
|
||||
{{#description}}
|
||||
{{#description}}
|
||||
/// {{{.}}}
|
||||
{{/description}}
|
||||
{{#isEnum}}
|
||||
@ -160,7 +256,55 @@ use crate::{models, types::*};
|
||||
length(min = {{minItems}}),
|
||||
{{/minItems}}
|
||||
{{/maxItems}}
|
||||
)]
|
||||
{{^isNullable}}
|
||||
{{#vendorExtensions.is-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
custom(function = "check_xss_string"),
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
custom(function = "check_xss_vec_string"),
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
custom(function = "check_xss_map_nested"),
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
custom(function = "check_xss_map"),
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
custom(function = "check_xss_map_string"),
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
{{/isNullable}}
|
||||
)]
|
||||
{{/hasValidation}}
|
||||
{{^hasValidation}}
|
||||
{{^isNullable}}
|
||||
{{#vendorExtensions.is-nested}}
|
||||
#[validate(nested)]
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
#[validate(nested)]
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
#[validate(custom(function = "check_xss_vec_string"))]
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
#[validate(custom(function = "check_xss_map_nested"))]
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
#[validate(custom(function = "check_xss_map"))]
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
#[validate(custom(function = "check_xss_map_string"))]
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
{{/isNullable}}
|
||||
{{/hasValidation}}
|
||||
{{#required}}
|
||||
pub {{{paramName}}}: {{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}},
|
||||
@ -204,10 +348,10 @@ use crate::{models, types::*};
|
||||
{{/pathParams.size}}
|
||||
{{#queryParams.size}}
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct {{{operationIdCamelCase}}}QueryParams {
|
||||
{{#queryParams}}
|
||||
{{#description}}
|
||||
{{#description}}
|
||||
/// {{{.}}}
|
||||
{{/description}}
|
||||
{{#isEnum}}
|
||||
@ -263,29 +407,77 @@ use crate::{models, types::*};
|
||||
length(min = {{minItems}}),
|
||||
{{/minItems}}
|
||||
{{/maxItems}}
|
||||
)]
|
||||
{{^isNullable}}
|
||||
{{#vendorExtensions.is-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
custom(function = "check_xss_string"),
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
custom(function = "check_xss_vec_string"),
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
custom(function = "check_xss_map_nested"),
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
custom(function = "check_xss_map"),
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
custom(function = "check_xss_map_string"),
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
{{/isNullable}}
|
||||
)]
|
||||
{{/hasValidation}}
|
||||
{{^hasValidation}}
|
||||
{{^isNullable}}
|
||||
{{#vendorExtensions.is-nested}}
|
||||
#[validate(nested)]
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
#[validate(nested)]
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
#[validate(custom(function = "check_xss_vec_string"))]
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
#[validate(custom(function = "check_xss_map_nested"))]
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
#[validate(custom(function = "check_xss_map"))]
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
#[validate(custom(function = "check_xss_map_string"))]
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
{{/isNullable}}
|
||||
{{/hasValidation}}
|
||||
{{#isArray}}
|
||||
{{#isNullable}}
|
||||
// Nullable array query parameters are not fully supported.
|
||||
{{/isNullable}}
|
||||
{{^required}}
|
||||
#[serde(default)]
|
||||
{{/required}}
|
||||
pub {{{paramName}}}: {{{dataType}}},
|
||||
{{/isArray}}
|
||||
{{#isNullable}}
|
||||
// Nullable array query parameters are not fully supported.
|
||||
{{/isNullable}}
|
||||
{{^required}}
|
||||
#[serde(default)]
|
||||
{{/required}}
|
||||
pub {{{paramName}}}: {{{dataType}}},
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{#required}}
|
||||
pub {{{paramName}}}: {{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}},
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{#isNullable}}
|
||||
#[serde(deserialize_with = "deserialize_optional_nullable")]
|
||||
#[serde(default = "default_optional_nullable")]
|
||||
{{/isNullable}}
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub {{{paramName}}}: Option<{{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}}>,
|
||||
{{/required}}
|
||||
{{#required}}
|
||||
pub {{{paramName}}}: {{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}},
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{#isNullable}}
|
||||
#[serde(deserialize_with = "deserialize_optional_nullable")]
|
||||
#[serde(default = "default_optional_nullable")]
|
||||
{{/isNullable}}
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub {{{paramName}}}: Option<{{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}}>,
|
||||
{{/required}}
|
||||
{{/isArray}}
|
||||
{{/queryParams}}
|
||||
}
|
||||
@ -313,7 +505,7 @@ use crate::{models, types::*};
|
||||
{{/isByteArray}}
|
||||
{{/pattern}}
|
||||
{{/hasValidation}}
|
||||
{{/queryParams}}
|
||||
{{/queryParams}}
|
||||
{{/queryParams.size}}
|
||||
{{/vendorExtensions}}
|
||||
{{/operation}}
|
||||
@ -345,6 +537,13 @@ pub enum {{{classname}}} {
|
||||
{{/allowableValues}}
|
||||
}
|
||||
|
||||
impl validator::Validate for {{{classname}}}
|
||||
{
|
||||
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for {{{classname}}} {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
@ -367,7 +566,7 @@ impl std::str::FromStr for {{{classname}}} {
|
||||
{{{value}}} => std::result::Result::Ok({{{classname}}}::{{{name}}}),
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
_ => std::result::Result::Err(format!("Value not valid: {}", s)),
|
||||
_ => std::result::Result::Err(format!(r#"Value not valid: {s}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -665,7 +864,7 @@ impl std::str::FromStr for {{{classname}}} {
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct {{{classname}}} {
|
||||
{{#vars}}
|
||||
{{#description}}
|
||||
{{#description}}
|
||||
/// {{{.}}}
|
||||
{{/description}}
|
||||
{{#isEnum}}
|
||||
@ -725,7 +924,55 @@ pub struct {{{classname}}} {
|
||||
length(min = {{minItems}}),
|
||||
{{/minItems}}
|
||||
{{/maxItems}}
|
||||
)]
|
||||
{{^isNullable}}
|
||||
{{#vendorExtensions.is-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
custom(function = "check_xss_string"),
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
nested,
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
custom(function = "check_xss_vec_string"),
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
custom(function = "check_xss_map_nested"),
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
custom(function = "check_xss_map"),
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
custom(function = "check_xss_map_string"),
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
{{/isNullable}}
|
||||
)]
|
||||
{{/hasValidation}}
|
||||
{{^hasValidation}}
|
||||
{{^isNullable}}
|
||||
{{#vendorExtensions.is-nested}}
|
||||
#[validate(nested)]
|
||||
{{/vendorExtensions.is-nested}}
|
||||
{{#vendorExtensions.is-string}}
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
{{/vendorExtensions.is-string}}
|
||||
{{#vendorExtensions.is-vec-nested}}
|
||||
#[validate(nested)]
|
||||
{{/vendorExtensions.is-vec-nested}}
|
||||
{{#vendorExtensions.is-vec-string}}
|
||||
#[validate(custom(function = "check_xss_vec_string"))]
|
||||
{{/vendorExtensions.is-vec-string}}
|
||||
{{#vendorExtensions.is-map-nested}}
|
||||
#[validate(custom(function = "check_xss_map_nested"))]
|
||||
{{/vendorExtensions.is-map-nested}}
|
||||
{{#vendorExtensions.is-map}}
|
||||
#[validate(custom(function = "check_xss_map"))]
|
||||
{{/vendorExtensions.is-map}}
|
||||
{{#vendorExtensions.is-map-string}}
|
||||
#[validate(custom(function = "check_xss_map_string"))]
|
||||
{{/vendorExtensions.is-map-string}}
|
||||
{{/isNullable}}
|
||||
{{/hasValidation}}
|
||||
{{#required}}
|
||||
pub {{{name}}}: {{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}},
|
||||
@ -958,9 +1205,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<{{{classname}}}>> for HeaderV
|
||||
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 {{classname}} - value: {} is invalid {}",
|
||||
hdr_value, e))
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(r#"Invalid header value for {{classname}} - value: {hdr_value} is invalid {e}"#))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -974,14 +1219,10 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<{{{classname
|
||||
std::result::Result::Ok(value) => {
|
||||
match <{{{classname}}} 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 {{classname}} - {}",
|
||||
value, err))
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(r#"Unable to convert header value '{value}' into {{classname}} - {err}"#))
|
||||
}
|
||||
},
|
||||
std::result::Result::Err(e) => std::result::Result::Err(
|
||||
format!("Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e))
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(r#"Unable to convert header: {hdr_value:?} to string: {e}"#))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,3 +16,5 @@
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
|
||||
{{>server-utils}}
|
||||
@ -59,9 +59,11 @@ async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A, E{
|
||||
) -> Result<Response, StatusCode>
|
||||
where
|
||||
I: AsRef<A> + Send + Sync,
|
||||
A: apis::{{classFilename}}::{{classnamePascalCase}}<E{{#havingAuthMethod}}, Claims = C{{/havingAuthMethod}}>{{#vendorExtensions}}{{#x-has-cookie-auth-methods}}+ apis::CookieAuthentication<Claims = C>{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}+ apis::ApiKeyAuthHeader<Claims = C>{{/x-has-header-auth-methods}}{{#x-has-basic-auth-methods}}+ apis::ApiAuthBasic<Claims = C>{{/x-has-basic-auth-methods}}{{/vendorExtensions}} + Send + Sync,
|
||||
A: {{#basicAnalytic}}apis::EventDispatcher + {{/basicAnalytic}}apis::{{classFilename}}::{{classnamePascalCase}}<E{{#havingAuthMethod}}, Claims = C{{/havingAuthMethod}}>{{#havingAuthMethod}}{{#basicAuthorization}} + apis::{{classFilename}}::{{classnamePascalCase}}Authorization<Claims = C>{{/basicAuthorization}}{{/havingAuthMethod}}{{#vendorExtensions}}{{#x-has-cookie-auth-methods}}+ apis::CookieAuthentication<Claims = C>{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}+ apis::ApiKeyAuthHeader<Claims = C>{{/x-has-header-auth-methods}}{{#x-has-basic-auth-methods}}+ apis::ApiAuthBasic<Claims = C>{{/x-has-basic-auth-methods}}{{/vendorExtensions}} + Send + Sync,
|
||||
E: std::fmt::Debug + Send + Sync + 'static,
|
||||
{
|
||||
{{#basicAnalytic}}let start_at = chrono::Utc::now();{{/basicAnalytic}}
|
||||
|
||||
{{#vendorExtensions}}
|
||||
{{#x-has-auth-methods}}
|
||||
// Authentication
|
||||
@ -88,10 +90,7 @@ where
|
||||
{{/x-has-basic-auth-methods}}
|
||||
;
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
{{/x-has-auth-methods}}
|
||||
{{/vendorExtensions}}
|
||||
@ -115,7 +114,7 @@ where
|
||||
Err(err) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!("Invalid header {{{baseName}}} - {}", err))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("Invalid header {{{baseName}}} - {err}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
|
||||
},
|
||||
},
|
||||
@ -197,30 +196,81 @@ where
|
||||
};
|
||||
{{/disableValidator}}
|
||||
|
||||
let result = api_impl.as_ref().{{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}(
|
||||
&method,
|
||||
&host,
|
||||
&cookies,
|
||||
{{#vendorExtensions}}
|
||||
{{#x-has-auth-methods}}
|
||||
{{#basicAuthorization}}
|
||||
{{#vendorExtensions}}
|
||||
// Authorization
|
||||
let authorization = api_impl.as_ref().{{{x-operation-id}}}_authorize(
|
||||
&method,
|
||||
&host,
|
||||
&cookies,
|
||||
&claims,
|
||||
{{#headerParams.size}}
|
||||
&header_params,
|
||||
{{/headerParams.size}}
|
||||
{{#pathParams.size}}
|
||||
&path_params,
|
||||
{{/pathParams.size}}
|
||||
{{#queryParams.size}}
|
||||
&query_params,
|
||||
{{/queryParams.size}}
|
||||
{{#vendorExtensions}}
|
||||
{{^x-consumes-multipart-related}}
|
||||
{{^x-consumes-multipart}}
|
||||
{{#bodyParams}}
|
||||
{{#-first}}
|
||||
&body,
|
||||
{{/-first}}
|
||||
{{/bodyParams}}
|
||||
{{/x-consumes-multipart}}
|
||||
{{/x-consumes-multipart-related}}
|
||||
{{#x-consumes-multipart}}
|
||||
&body,
|
||||
{{/x-consumes-multipart}}
|
||||
{{#x-consumes-multipart-related}}
|
||||
&body,
|
||||
{{/x-consumes-multipart-related}}
|
||||
{{/vendorExtensions}}
|
||||
).await;
|
||||
match authorization {
|
||||
Ok(authorization) => match authorization {
|
||||
apis::Authorization::Authorized => {},
|
||||
apis::Authorization::Forbidden => { return response_with_status_code_only(StatusCode::FORBIDDEN); },
|
||||
},
|
||||
Err(_) => { return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR); }
|
||||
}
|
||||
{{/vendorExtensions}}
|
||||
{{/basicAuthorization}}
|
||||
{{/x-has-auth-methods}}
|
||||
{{/vendorExtensions}}
|
||||
|
||||
{{#basicAnalytic}}let mut event = apis::event::Event::default();{{/basicAnalytic}}
|
||||
let result = api_impl.as_ref().{{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}(
|
||||
{{#basicAnalytic}}&mut event,{{/basicAnalytic}}
|
||||
{{^ownedRequest}}&{{/ownedRequest}}method,
|
||||
{{^ownedRequest}}&{{/ownedRequest}}host,
|
||||
{{^ownedRequest}}&{{/ownedRequest}}cookies,
|
||||
{{#vendorExtensions}}
|
||||
{{#x-has-auth-methods}}
|
||||
&claims,
|
||||
{{^ownedRequest}}&{{/ownedRequest}}claims,
|
||||
{{/x-has-auth-methods}}
|
||||
{{/vendorExtensions}}
|
||||
{{#headerParams.size}}
|
||||
&header_params,
|
||||
{{^ownedRequest}}&{{/ownedRequest}}header_params,
|
||||
{{/headerParams.size}}
|
||||
{{#pathParams.size}}
|
||||
&path_params,
|
||||
{{^ownedRequest}}&{{/ownedRequest}}path_params,
|
||||
{{/pathParams.size}}
|
||||
{{#queryParams.size}}
|
||||
&query_params,
|
||||
{{^ownedRequest}}&{{/ownedRequest}}query_params,
|
||||
{{/queryParams.size}}
|
||||
{{#vendorExtensions}}
|
||||
{{^x-consumes-multipart-related}}
|
||||
{{^x-consumes-multipart}}
|
||||
{{#bodyParams}}
|
||||
{{#-first}}
|
||||
&body,
|
||||
{{^ownedRequest}}&{{/ownedRequest}}body,
|
||||
{{/-first}}
|
||||
{{/bodyParams}}
|
||||
{{/x-consumes-multipart}}
|
||||
@ -276,7 +326,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling {{name}} header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling {{name}} header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -354,12 +404,28 @@ where
|
||||
},
|
||||
{{/responses}}
|
||||
},
|
||||
Err(why) => {
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
Err({{#ownedRequest}}_{{/ownedRequest}}why) => {
|
||||
{{^ownedRequest}}
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
{{/ownedRequest}}
|
||||
{{#ownedRequest}}
|
||||
return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
{{/ownedRequest}}
|
||||
},
|
||||
};
|
||||
|
||||
{{#basicAnalytic}}
|
||||
if let Ok(resp) = resp.as_ref() && !event.is_empty() {
|
||||
event.insert(apis::event::convention::EVENT_TIMESTAMP.to_string(), format!("{start_at:?}"));
|
||||
event.insert(apis::event::convention::EVENT_SERVICE.to_string(), api_impl.as_ref().service_name());
|
||||
event.insert(apis::event::convention::EVENT_STATUS_CODE.to_string(), resp.status().as_u16().to_string());
|
||||
event.insert(apis::event::convention::EVENT_ACTION.to_string(), "{{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}".to_string());
|
||||
event.insert(apis::event::convention::EVENT_LATENCY_SECS.to_string(), format!("{:.6}", chrono::Utc::now().signed_duration_since(start_at).as_seconds_f64()));
|
||||
api_impl.as_ref().dispatch(event).await;
|
||||
}
|
||||
{{/basicAnalytic}}
|
||||
|
||||
resp.map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR })
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
pub fn new<I, A, E{{#havingAuthMethods}}, C{{/havingAuthMethods}}>(api_impl: I) -> Router
|
||||
where
|
||||
I: AsRef<A> + Clone + Send + Sync + 'static,
|
||||
A: {{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}}<E{{#havingAuthMethod}}, Claims = C{{/havingAuthMethod}}> + {{/operations}}{{/apis}}{{/apiInfo}}{{#authMethods}}{{#isApiKey}}{{#isKeyInCookie}}apis::CookieAuthentication<Claims = C> + {{/isKeyInCookie}}{{#isKeyInHeader}}apis::ApiKeyAuthHeader<Claims = C> + {{/isKeyInHeader}}{{/isApiKey}}{{#isBasic}}apis::ApiAuthBasic<Claims = C> + {{/isBasic}}{{/authMethods}}Send + Sync + 'static,
|
||||
A: {{#basicAnalytic}}apis::EventDispatcher + {{/basicAnalytic}}{{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}}<E{{#havingAuthMethod}}, Claims = C{{/havingAuthMethod}}>{{#havingAuthMethod}}{{#basicAuthorization}} + apis::{{classFilename}}::{{classnamePascalCase}}Authorization<Claims = C>{{/basicAuthorization}}{{/havingAuthMethod}} + {{/operations}}{{/apis}}{{/apiInfo}}{{#authMethods}}{{#isApiKey}}{{#isKeyInCookie}}apis::CookieAuthentication<Claims = C> + {{/isKeyInCookie}}{{#isKeyInHeader}}apis::ApiKeyAuthHeader<Claims = C> + {{/isKeyInHeader}}{{/isApiKey}}{{#isBasic}}apis::ApiAuthBasic<Claims = C> + {{/isBasic}}{{/authMethods}}Send + Sync + 'static,
|
||||
E: std::fmt::Debug + Send + Sync + 'static,
|
||||
{{#havingAuthMethods}}C: Send + Sync + 'static,{{/havingAuthMethods}}
|
||||
{
|
||||
|
||||
8
modules/openapi-generator/src/main/resources/rust-axum/server-utils.mustache
vendored
Normal file
8
modules/openapi-generator/src/main/resources/rust-axum/server-utils.mustache
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
17
pom.xml
17
pom.xml
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.sonatype.oss</groupId>
|
||||
<artifactId>oss-parent</artifactId>
|
||||
<version>5</version>
|
||||
<relativePath />
|
||||
<relativePath/>
|
||||
<!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@ -180,8 +180,10 @@
|
||||
<argLine>@{argLine} -XX:+StartAttachListener</argLine>
|
||||
<rerunFailingTestsCount>2</rerunFailingTestsCount>
|
||||
<systemPropertyVariables>
|
||||
<org.openapitools.codegen.utils.oncelogger.expiry>1000</org.openapitools.codegen.utils.oncelogger.expiry>
|
||||
<org.openapitools.codegen.utils.oncelogger.cachesize>5000</org.openapitools.codegen.utils.oncelogger.cachesize>
|
||||
<org.openapitools.codegen.utils.oncelogger.expiry>1000
|
||||
</org.openapitools.codegen.utils.oncelogger.expiry>
|
||||
<org.openapitools.codegen.utils.oncelogger.cachesize>5000
|
||||
</org.openapitools.codegen.utils.oncelogger.cachesize>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
@ -509,7 +511,8 @@
|
||||
<!-- https://spotbugs.readthedocs.io/en/stable/effort.html -->
|
||||
<effort>min</effort>
|
||||
<excludeFilterFile>
|
||||
${project.basedir}${file.separator}spotbugs-exclude.xml</excludeFilterFile>
|
||||
${project.basedir}${file.separator}spotbugs-exclude.xml
|
||||
</excludeFilterFile>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@ -1232,7 +1235,7 @@
|
||||
<junit.version>5.10.2</junit.version>
|
||||
<kotlin.version>1.6.21</kotlin.version>
|
||||
<kotlin-compiler-embeddable.version>1.6.21</kotlin-compiler-embeddable.version>
|
||||
<lombok.version>1.18.30</lombok.version>
|
||||
<lombok.version>1.18.38</lombok.version>
|
||||
<maven-dependency-plugin.version>3.8.1</maven-dependency-plugin.version>
|
||||
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
|
||||
<maven-jar-plugin.version>3.4.2</maven-jar-plugin.version>
|
||||
|
||||
2
samples/server/petstore/rust-axum/output/apikey-authorization/.gitignore
vendored
Normal file
2
samples/server/petstore/rust-axum/output/apikey-authorization/.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.15.0-SNAPSHOT
|
||||
@ -0,0 +1,47 @@
|
||||
[package]
|
||||
name = "apikey-authorization"
|
||||
version = "1.0.0"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "Checkout Basic"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
server = []
|
||||
conversion = [
|
||||
"frunk",
|
||||
"frunk_derives",
|
||||
"frunk_core",
|
||||
"frunk-enum-core",
|
||||
"frunk-enum-derive",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
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_html_form = "0.2"
|
||||
serde_json = { version = "1", features = ["raw_value"] }
|
||||
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.20", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tracing-subscriber = "0.3"
|
||||
@ -0,0 +1,93 @@
|
||||
# Rust API for apikey-authorization
|
||||
|
||||
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.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
This autogenerated project defines an API crate `apikey-authorization` 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_authorization::apis::default::Api for ServerImpl {
|
||||
// API implementation goes here
|
||||
}
|
||||
|
||||
impl apikey_authorization::apis::ErrorHandler for ServerImpl {}
|
||||
|
||||
pub async fn start_server(addr: &str) {
|
||||
// initialize tracing
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
// Init Axum router
|
||||
let app = apikey_authorization::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,98 @@
|
||||
pub mod payments;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Authorization {
|
||||
Authorized,
|
||||
Forbidden,
|
||||
}
|
||||
|
||||
pub mod event {
|
||||
/// Anything to be recorded.
|
||||
pub type Event = std::collections::HashMap<String, String>;
|
||||
|
||||
pub mod convention {
|
||||
pub const EVENT_SERVICE: &str = "_service_";
|
||||
pub const EVENT_ACTOR: &str = "_actor_";
|
||||
pub const EVENT_ACTION: &str = "_action_";
|
||||
pub const EVENT_RESOURCE_TYPE: &str = "_resource_type_";
|
||||
pub const EVENT_RESOURCE: &str = "_resource_";
|
||||
pub const EVENT_STATUS_CODE: &str = "_status_code_";
|
||||
pub const EVENT_LATENCY_SECS: &str = "_latency_secs_";
|
||||
pub const EVENT_TIMESTAMP: &str = "timestamp";
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait EventDispatcher {
|
||||
fn service_name(&self) -> String;
|
||||
async fn dispatch(&self, event: event::Event) {}
|
||||
}
|
||||
|
||||
/// API Key Authentication - Header.
|
||||
#[async_trait::async_trait]
|
||||
pub trait ApiKeyAuthHeader {
|
||||
type Claims;
|
||||
|
||||
/// Extracting Claims from Header. Return None if the Claims are invalid.
|
||||
async fn extract_claims_from_header(
|
||||
&self,
|
||||
headers: &axum::http::header::HeaderMap,
|
||||
key: &str,
|
||||
) -> Option<Self::Claims>;
|
||||
}
|
||||
|
||||
/// Cookie Authentication.
|
||||
#[async_trait::async_trait]
|
||||
pub trait CookieAuthentication {
|
||||
type Claims;
|
||||
|
||||
/// Extracting Claims from Cookie. Return None if the Claims are invalid.
|
||||
async fn extract_claims_from_cookie(
|
||||
&self,
|
||||
cookies: &axum_extra::extract::CookieJar,
|
||||
key: &str,
|
||||
) -> Option<Self::Claims>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum BasicAuthKind {
|
||||
Basic,
|
||||
Bearer,
|
||||
}
|
||||
|
||||
/// API Key Authentication - Authentication Header.
|
||||
/// For `Basic token` and `Bearer token`
|
||||
#[async_trait::async_trait]
|
||||
pub trait ApiAuthBasic {
|
||||
type Claims;
|
||||
|
||||
/// Extracting Claims from Header. Return None if the Claims are invalid.
|
||||
async fn extract_claims_from_auth_header(
|
||||
&self,
|
||||
kind: BasicAuthKind,
|
||||
headers: &axum::http::header::HeaderMap,
|
||||
key: &str,
|
||||
) -> Option<Self::Claims>;
|
||||
}
|
||||
|
||||
// Error handler for unhandled errors.
|
||||
#[async_trait::async_trait]
|
||||
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
|
||||
#[allow(unused_variables)]
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn handle_error(
|
||||
&self,
|
||||
method: &::http::Method,
|
||||
host: &axum_extra::extract::Host,
|
||||
cookies: &axum_extra::extract::CookieJar,
|
||||
error: E,
|
||||
) -> Result<axum::response::Response, http::StatusCode> {
|
||||
tracing::error!("Unhandled error: {:?}", error);
|
||||
axum::response::Response::builder()
|
||||
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(axum::body::Body::empty())
|
||||
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
use async_trait::async_trait;
|
||||
use axum::extract::*;
|
||||
use axum_extra::extract::{CookieJar, Host};
|
||||
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 APIs - Authorization.
|
||||
#[async_trait]
|
||||
#[allow(clippy::ptr_arg)]
|
||||
pub trait PaymentsAuthorization {
|
||||
type Claims;
|
||||
|
||||
/// Authorization - Get payment method by id.
|
||||
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
|
||||
async fn get_payment_method_by_id_authorize(
|
||||
&self,
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
claims: &Self::Claims,
|
||||
path_params: &models::GetPaymentMethodByIdPathParams,
|
||||
) -> Result<super::Authorization, ()> {
|
||||
Ok(super::Authorization::Authorized)
|
||||
}
|
||||
|
||||
/// Authorization - Get payment methods.
|
||||
/// GetPaymentMethods - GET /v71/paymentMethods
|
||||
async fn get_payment_methods_authorize(
|
||||
&self,
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
claims: &Self::Claims,
|
||||
) -> Result<super::Authorization, ()> {
|
||||
Ok(super::Authorization::Authorized)
|
||||
}
|
||||
|
||||
/// Authorization - Make a payment.
|
||||
/// PostMakePayment - POST /v71/payments
|
||||
async fn post_make_payment_authorize(
|
||||
&self,
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
claims: &Self::Claims,
|
||||
body: &Option<models::Payment>,
|
||||
) -> Result<super::Authorization, ()> {
|
||||
Ok(super::Authorization::Authorized)
|
||||
}
|
||||
}
|
||||
|
||||
/// Payments
|
||||
#[async_trait]
|
||||
#[allow(clippy::ptr_arg)]
|
||||
pub trait Payments<E: std::fmt::Debug + Send + Sync + 'static = ()>:
|
||||
super::ErrorHandler<E>
|
||||
{
|
||||
type Claims;
|
||||
|
||||
/// Get payment method by id.
|
||||
///
|
||||
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
|
||||
async fn get_payment_method_by_id(
|
||||
&self,
|
||||
event: &mut super::event::Event,
|
||||
method: Method,
|
||||
host: Host,
|
||||
cookies: CookieJar,
|
||||
claims: Self::Claims,
|
||||
path_params: models::GetPaymentMethodByIdPathParams,
|
||||
) -> Result<GetPaymentMethodByIdResponse, E>;
|
||||
|
||||
/// Get payment methods.
|
||||
///
|
||||
/// GetPaymentMethods - GET /v71/paymentMethods
|
||||
async fn get_payment_methods(
|
||||
&self,
|
||||
event: &mut super::event::Event,
|
||||
method: Method,
|
||||
host: Host,
|
||||
cookies: CookieJar,
|
||||
claims: Self::Claims,
|
||||
) -> Result<GetPaymentMethodsResponse, E>;
|
||||
|
||||
/// Make a payment.
|
||||
///
|
||||
/// PostMakePayment - POST /v71/payments
|
||||
async fn post_make_payment(
|
||||
&self,
|
||||
event: &mut super::event::Event,
|
||||
method: Method,
|
||||
host: Host,
|
||||
cookies: CookieJar,
|
||||
claims: Self::Claims,
|
||||
body: Option<models::Payment>,
|
||||
) -> Result<PostMakePaymentResponse, E>;
|
||||
}
|
||||
@ -0,0 +1,188 @@
|
||||
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!(
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {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!(
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {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!(
|
||||
r#"Unable to convert {hdr_value:?} into a header - {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!(r#"Unable to convert header {hdr_value:?} to {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!(
|
||||
r#"Unable to convert {hdr_value:?} from a header {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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
r#"Unable to convert {hdr_value:?} from a header {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!(
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
r#"Unable to convert header {hdr_value:?} to string {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!(
|
||||
r#"Unable to convert {hdr_value:?} to a header: {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,891 @@
|
||||
#![allow(unused_qualifications)]
|
||||
|
||||
use http::HeaderValue;
|
||||
use validator::Validate;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[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), custom(function = "check_xss_string"))]
|
||||
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!(
|
||||
r#"Invalid header value for Amount - value: {hdr_value} is invalid {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!(
|
||||
r#"Unable to convert header value '{value}' into Amount - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {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")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub code: String,
|
||||
|
||||
/// User-friendly message
|
||||
#[serde(rename = "message")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
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!(
|
||||
r#"Invalid header value for CheckoutError - value: {hdr_value} is invalid {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!(
|
||||
r#"Unable to convert header value '{value}' into CheckoutError - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct Payment {
|
||||
#[serde(rename = "paymentMethod")]
|
||||
#[validate(nested)]
|
||||
pub payment_method: models::PaymentMethod,
|
||||
|
||||
#[serde(rename = "amount")]
|
||||
#[validate(nested)]
|
||||
pub amount: models::Amount,
|
||||
|
||||
#[serde(rename = "merchantAccount")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub merchant_account: String,
|
||||
|
||||
#[serde(rename = "reference")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reference: Option<String>,
|
||||
|
||||
/// Note: inline enums are not fully supported by openapi-generator
|
||||
#[serde(rename = "channel")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[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!(
|
||||
r#"Invalid header value for Payment - value: {hdr_value} is invalid {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!(
|
||||
r#"Unable to convert header value '{value}' into Payment - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {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")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Type of the payment method
|
||||
#[serde(rename = "type")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[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!(
|
||||
r#"Invalid header value for PaymentMethod - value: {hdr_value} is invalid {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!(
|
||||
r#"Unable to convert header value '{value}' into PaymentMethod - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {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")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub psp_reference: String,
|
||||
|
||||
/// Result code
|
||||
/// Note: inline enums are not fully supported by openapi-generator
|
||||
#[serde(rename = "resultCode")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
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!(
|
||||
r#"Invalid header value for PaymentResult - value: {hdr_value} is invalid {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!(
|
||||
r#"Unable to convert header value '{value}' into PaymentResult - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,545 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
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, E, C>(api_impl: I) -> Router
|
||||
where
|
||||
I: AsRef<A> + Clone + Send + Sync + 'static,
|
||||
A: apis::EventDispatcher
|
||||
+ apis::payments::Payments<E, Claims = C>
|
||||
+ apis::payments::PaymentsAuthorization<Claims = C>
|
||||
+ apis::ApiAuthBasic<Claims = C>
|
||||
+ apis::ApiAuthBasic<Claims = C>
|
||||
+ apis::ApiKeyAuthHeader<Claims = C>
|
||||
+ apis::CookieAuthentication<Claims = C>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
E: std::fmt::Debug + Send + Sync + 'static,
|
||||
C: Send + Sync + 'static,
|
||||
{
|
||||
// build our application with a route
|
||||
Router::new()
|
||||
.route(
|
||||
"/v71/paymentMethods",
|
||||
get(get_payment_methods::<I, A, E, C>),
|
||||
)
|
||||
.route(
|
||||
"/v71/paymentMethods/{id}",
|
||||
get(get_payment_method_by_id::<I, A, E, C>),
|
||||
)
|
||||
.route("/v71/payments", post(post_make_payment::<I, A, E, C>))
|
||||
.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, E, C>(
|
||||
method: Method,
|
||||
host: Host,
|
||||
cookies: CookieJar,
|
||||
headers: HeaderMap,
|
||||
Path(path_params): Path<models::GetPaymentMethodByIdPathParams>,
|
||||
State(api_impl): State<I>,
|
||||
) -> Result<Response, StatusCode>
|
||||
where
|
||||
I: AsRef<A> + Send + Sync,
|
||||
A: apis::EventDispatcher
|
||||
+ apis::payments::Payments<E, Claims = C>
|
||||
+ apis::payments::PaymentsAuthorization<Claims = C>
|
||||
+ apis::ApiAuthBasic<Claims = C>
|
||||
+ Send
|
||||
+ Sync,
|
||||
E: std::fmt::Debug + Send + Sync + 'static,
|
||||
{
|
||||
let start_at = chrono::Utc::now();
|
||||
|
||||
// Authentication
|
||||
let claims_in_auth_header = api_impl
|
||||
.as_ref()
|
||||
.extract_claims_from_auth_header(apis::BasicAuthKind::Bearer, &headers, "authorization")
|
||||
.await;
|
||||
let claims = None.or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[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);
|
||||
};
|
||||
|
||||
// Authorization
|
||||
let authorization = api_impl
|
||||
.as_ref()
|
||||
.get_payment_method_by_id_authorize(&method, &host, &cookies, &claims, &path_params)
|
||||
.await;
|
||||
match authorization {
|
||||
Ok(authorization) => match authorization {
|
||||
apis::Authorization::Authorized => {}
|
||||
apis::Authorization::Forbidden => {
|
||||
return response_with_status_code_only(StatusCode::FORBIDDEN);
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
let mut event = apis::event::Event::default();
|
||||
let result = api_impl
|
||||
.as_ref()
|
||||
.get_payment_method_by_id(&mut event, method, host, cookies, claims, 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(_why) => {
|
||||
return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(resp) = resp.as_ref()
|
||||
&& !event.is_empty()
|
||||
{
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_TIMESTAMP.to_string(),
|
||||
format!("{start_at:?}"),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_SERVICE.to_string(),
|
||||
api_impl.as_ref().service_name(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_STATUS_CODE.to_string(),
|
||||
resp.status().as_u16().to_string(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_ACTION.to_string(),
|
||||
"get_payment_method_by_id".to_string(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_LATENCY_SECS.to_string(),
|
||||
format!(
|
||||
"{:.6}",
|
||||
chrono::Utc::now()
|
||||
.signed_duration_since(start_at)
|
||||
.as_seconds_f64()
|
||||
),
|
||||
);
|
||||
api_impl.as_ref().dispatch(event).await;
|
||||
}
|
||||
|
||||
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, E, C>(
|
||||
method: Method,
|
||||
host: Host,
|
||||
cookies: CookieJar,
|
||||
headers: HeaderMap,
|
||||
State(api_impl): State<I>,
|
||||
) -> Result<Response, StatusCode>
|
||||
where
|
||||
I: AsRef<A> + Send + Sync,
|
||||
A: apis::EventDispatcher
|
||||
+ apis::payments::Payments<E, Claims = C>
|
||||
+ apis::payments::PaymentsAuthorization<Claims = C>
|
||||
+ apis::ApiAuthBasic<Claims = C>
|
||||
+ Send
|
||||
+ Sync,
|
||||
E: std::fmt::Debug + Send + Sync + 'static,
|
||||
{
|
||||
let start_at = chrono::Utc::now();
|
||||
|
||||
// Authentication
|
||||
let claims_in_auth_header = api_impl
|
||||
.as_ref()
|
||||
.extract_claims_from_auth_header(apis::BasicAuthKind::Bearer, &headers, "authorization")
|
||||
.await;
|
||||
let claims = None.or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[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);
|
||||
};
|
||||
|
||||
// Authorization
|
||||
let authorization = api_impl
|
||||
.as_ref()
|
||||
.get_payment_methods_authorize(&method, &host, &cookies, &claims)
|
||||
.await;
|
||||
match authorization {
|
||||
Ok(authorization) => match authorization {
|
||||
apis::Authorization::Authorized => {}
|
||||
apis::Authorization::Forbidden => {
|
||||
return response_with_status_code_only(StatusCode::FORBIDDEN);
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
let mut event = apis::event::Event::default();
|
||||
let result = api_impl
|
||||
.as_ref()
|
||||
.get_payment_methods(&mut event, method, host, cookies, claims)
|
||||
.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(_why) => {
|
||||
return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(resp) = resp.as_ref()
|
||||
&& !event.is_empty()
|
||||
{
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_TIMESTAMP.to_string(),
|
||||
format!("{start_at:?}"),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_SERVICE.to_string(),
|
||||
api_impl.as_ref().service_name(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_STATUS_CODE.to_string(),
|
||||
resp.status().as_u16().to_string(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_ACTION.to_string(),
|
||||
"get_payment_methods".to_string(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_LATENCY_SECS.to_string(),
|
||||
format!(
|
||||
"{:.6}",
|
||||
chrono::Utc::now()
|
||||
.signed_duration_since(start_at)
|
||||
.as_seconds_f64()
|
||||
),
|
||||
);
|
||||
api_impl.as_ref().dispatch(event).await;
|
||||
}
|
||||
|
||||
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, E, C>(
|
||||
method: Method,
|
||||
host: Host,
|
||||
cookies: CookieJar,
|
||||
headers: HeaderMap,
|
||||
State(api_impl): State<I>,
|
||||
Json(body): Json<Option<models::Payment>>,
|
||||
) -> Result<Response, StatusCode>
|
||||
where
|
||||
I: AsRef<A> + Send + Sync,
|
||||
A: apis::EventDispatcher
|
||||
+ apis::payments::Payments<E, Claims = C>
|
||||
+ apis::payments::PaymentsAuthorization<Claims = C>
|
||||
+ apis::CookieAuthentication<Claims = C>
|
||||
+ apis::ApiAuthBasic<Claims = C>
|
||||
+ Send
|
||||
+ Sync,
|
||||
E: std::fmt::Debug + Send + Sync + 'static,
|
||||
{
|
||||
let start_at = chrono::Utc::now();
|
||||
|
||||
// Authentication
|
||||
let claims_in_cookie = api_impl
|
||||
.as_ref()
|
||||
.extract_claims_from_cookie(&cookies, "X-API-Key")
|
||||
.await;
|
||||
let claims_in_auth_header = api_impl
|
||||
.as_ref()
|
||||
.extract_claims_from_auth_header(apis::BasicAuthKind::Bearer, &headers, "authorization")
|
||||
.await;
|
||||
let claims = None.or(claims_in_cookie).or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[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);
|
||||
};
|
||||
|
||||
// Authorization
|
||||
let authorization = api_impl
|
||||
.as_ref()
|
||||
.post_make_payment_authorize(&method, &host, &cookies, &claims, &body)
|
||||
.await;
|
||||
match authorization {
|
||||
Ok(authorization) => match authorization {
|
||||
apis::Authorization::Authorized => {}
|
||||
apis::Authorization::Forbidden => {
|
||||
return response_with_status_code_only(StatusCode::FORBIDDEN);
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
let mut event = apis::event::Event::default();
|
||||
let result = api_impl
|
||||
.as_ref()
|
||||
.post_make_payment(&mut event, method, host, cookies, claims, 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(_why) => {
|
||||
return response_with_status_code_only(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(resp) = resp.as_ref()
|
||||
&& !event.is_empty()
|
||||
{
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_TIMESTAMP.to_string(),
|
||||
format!("{start_at:?}"),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_SERVICE.to_string(),
|
||||
api_impl.as_ref().service_name(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_STATUS_CODE.to_string(),
|
||||
resp.status().as_u16().to_string(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_ACTION.to_string(),
|
||||
"post_make_payment".to_string(),
|
||||
);
|
||||
event.insert(
|
||||
apis::event::convention::EVENT_LATENCY_SECS.to_string(),
|
||||
format!(
|
||||
"{:.6}",
|
||||
chrono::Utc::now()
|
||||
.signed_duration_since(start_at)
|
||||
.as_seconds_f64()
|
||||
),
|
||||
);
|
||||
api_impl.as_ref().dispatch(event).await;
|
||||
}
|
||||
|
||||
resp.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
@ -0,0 +1,790 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::types::Nullable;
|
||||
///
|
||||
/// let x = Nullable::Present("value");
|
||||
/// assert_eq!(x.expect("the world is ending"), "value");
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use apikey_authorization::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_authorization::types::Nullable;
|
||||
///
|
||||
/// let x = Nullable::Present("air");
|
||||
/// assert_eq!(x.unwrap(), "air");
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use apikey_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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_authorization::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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> validator::Validate for Nullable<T>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
fn validate(&self) -> Result<(), validator::ValidationErrors> {
|
||||
match self {
|
||||
Self::Present(x) => x.validate(),
|
||||
Self::Null => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> validator::ValidateArgs<'a> for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateArgs<'a>,
|
||||
{
|
||||
type Args = T::Args;
|
||||
fn validate_with_args(&self, args: Self::Args) -> Result<(), validator::ValidationErrors> {
|
||||
match self {
|
||||
Self::Present(x) => x.validate_with_args(args),
|
||||
Self::Null => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> validator::ValidateContains for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateContains,
|
||||
{
|
||||
fn validate_contains(&self, needle: &str) -> bool {
|
||||
match self {
|
||||
Self::Present(x) => x.validate_contains(needle),
|
||||
Self::Null => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> validator::ValidateRequired for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateRequired,
|
||||
{
|
||||
fn is_some(&self) -> bool {
|
||||
self.is_present()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> validator::ValidateRegex for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateRegex,
|
||||
{
|
||||
fn validate_regex(&self, regex: impl validator::AsRegex) -> bool {
|
||||
match self {
|
||||
Self::Present(x) => x.validate_regex(regex),
|
||||
Self::Null => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, I> validator::ValidateRange<I> for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateRange<I>,
|
||||
{
|
||||
fn greater_than(&self, max: I) -> Option<bool> {
|
||||
use validator::ValidateRange;
|
||||
match self {
|
||||
Self::Present(x) => x.greater_than(max),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
fn less_than(&self, min: I) -> Option<bool> {
|
||||
use validator::ValidateRange;
|
||||
match self {
|
||||
Self::Present(x) => x.less_than(min),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, I> validator::ValidateLength<I> for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateLength<I>,
|
||||
I: PartialEq + PartialOrd,
|
||||
{
|
||||
fn length(&self) -> Option<I> {
|
||||
use validator::ValidateLength;
|
||||
match self {
|
||||
Self::Present(x) => x.length(),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Nullable<T>> for Option<T> {
|
||||
fn from(value: Nullable<T>) -> Option<T> {
|
||||
match value {
|
||||
Nullable::Present(x) => Some(x),
|
||||
Nullable::Null => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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")),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -3,7 +3,7 @@ name = "apikey-auths"
|
||||
version = "1.0.0"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "Checkout Basic"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
@ -17,6 +17,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ pub trait Payments<E: std::fmt::Debug + Send + Sync + 'static = ()>:
|
||||
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
|
||||
async fn get_payment_method_by_id(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -60,6 +61,7 @@ pub trait Payments<E: std::fmt::Debug + Send + Sync + 'static = ()>:
|
||||
/// GetPaymentMethods - GET /v71/paymentMethods
|
||||
async fn get_payment_methods(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -71,6 +73,7 @@ pub trait Payments<E: std::fmt::Debug + Send + Sync + 'static = ()>:
|
||||
/// PostMakePayment - POST /v71/payments
|
||||
async fn post_make_payment(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,60 @@ use validator::Validate;
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct GetPaymentMethodByIdPathParams {
|
||||
@ -19,7 +73,7 @@ pub struct GetPaymentMethodByIdPathParams {
|
||||
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))]
|
||||
#[validate(length(min = 3, max = 3), custom(function = "check_xss_string"))]
|
||||
pub currency: String,
|
||||
|
||||
/// The amount of the transaction, in [minor units](https://docs.adyen.com/development-resources/currency-codes).
|
||||
@ -81,7 +135,7 @@ impl std::str::FromStr for Amount {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing Amount".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -99,7 +153,7 @@ impl std::str::FromStr for Amount {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing Amount".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,8 +191,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<Amount>> for HeaderValue {
|
||||
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
|
||||
r#"Invalid header value for Amount - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,14 +209,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Amount> {
|
||||
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
|
||||
r#"Unable to convert header value '{value}' into Amount - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -174,10 +225,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Amount> {
|
||||
pub struct CheckoutError {
|
||||
/// Error code
|
||||
#[serde(rename = "code")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub code: String,
|
||||
|
||||
/// User-friendly message
|
||||
#[serde(rename = "message")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
@ -235,7 +288,7 @@ impl std::str::FromStr for CheckoutError {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing CheckoutError".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -253,7 +306,7 @@ impl std::str::FromStr for CheckoutError {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing CheckoutError".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,8 +344,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<CheckoutError>> for HeaderVal
|
||||
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
|
||||
r#"Invalid header value for CheckoutError - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -310,14 +362,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<CheckoutErro
|
||||
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
|
||||
r#"Unable to convert header value '{value}' into CheckoutError - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -327,20 +377,25 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<CheckoutErro
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct Payment {
|
||||
#[serde(rename = "paymentMethod")]
|
||||
#[validate(nested)]
|
||||
pub payment_method: models::PaymentMethod,
|
||||
|
||||
#[serde(rename = "amount")]
|
||||
#[validate(nested)]
|
||||
pub amount: models::Amount,
|
||||
|
||||
#[serde(rename = "merchantAccount")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub merchant_account: String,
|
||||
|
||||
#[serde(rename = "reference")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reference: Option<String>,
|
||||
|
||||
/// Note: inline enums are not fully supported by openapi-generator
|
||||
#[serde(rename = "channel")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub channel: Option<String>,
|
||||
}
|
||||
@ -419,7 +474,7 @@ impl std::str::FromStr for Payment {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing Payment".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -451,7 +506,7 @@ impl std::str::FromStr for Payment {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing Payment".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,8 +551,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<Payment>> for HeaderValue {
|
||||
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
|
||||
r#"Invalid header value for Payment - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -515,14 +569,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Payment> {
|
||||
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
|
||||
r#"Unable to convert header value '{value}' into Payment - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -534,11 +586,13 @@ pub struct PaymentMethod {
|
||||
/// Name of the payment method
|
||||
/// Note: inline enums are not fully supported by openapi-generator
|
||||
#[serde(rename = "name")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Type of the payment method
|
||||
#[serde(rename = "type")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub r#type: Option<String>,
|
||||
}
|
||||
@ -602,7 +656,7 @@ impl std::str::FromStr for PaymentMethod {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing PaymentMethod".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -620,7 +674,7 @@ impl std::str::FromStr for PaymentMethod {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing PaymentMethod".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -650,8 +704,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<PaymentMethod>> for HeaderVal
|
||||
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
|
||||
r#"Invalid header value for PaymentMethod - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -669,14 +722,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<PaymentMetho
|
||||
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
|
||||
r#"Unable to convert header value '{value}' into PaymentMethod - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -687,11 +738,13 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<PaymentMetho
|
||||
pub struct PaymentResult {
|
||||
/// PSP ref
|
||||
#[serde(rename = "pspReference")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub psp_reference: String,
|
||||
|
||||
/// Result code
|
||||
/// Note: inline enums are not fully supported by openapi-generator
|
||||
#[serde(rename = "resultCode")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub result_code: String,
|
||||
}
|
||||
|
||||
@ -752,7 +805,7 @@ impl std::str::FromStr for PaymentResult {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing PaymentResult".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -770,7 +823,7 @@ impl std::str::FromStr for PaymentResult {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing PaymentResult".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -808,8 +861,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<PaymentResult>> for HeaderVal
|
||||
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
|
||||
r#"Invalid header value for PaymentResult - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -827,14 +879,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<PaymentResul
|
||||
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
|
||||
r#"Unable to convert header value '{value}' into PaymentResult - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -71,10 +71,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -187,10 +184,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -302,10 +296,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_cookie).or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -391,3 +382,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -3,7 +3,7 @@ name = "multipart-v3"
|
||||
version = "1.0.7"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "API under test"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
@ -17,6 +17,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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.7
|
||||
- Generator version: 7.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MultipartRelatedRequestPost - POST /multipart_related_request
|
||||
async fn multipart_related_request_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -47,6 +48,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MultipartRequestPost - POST /multipart_request
|
||||
async fn multipart_request_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -56,6 +58,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MultipleIdenticalMimeTypesPost - POST /multiple-identical-mime-types
|
||||
async fn multiple_identical_mime_types_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,10 +7,65 @@ use validator::Validate;
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct MultipartRelatedRequest {
|
||||
#[serde(rename = "object_field")]
|
||||
#[validate(nested)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub object_field: Option<models::MultipartRequestObjectField>,
|
||||
|
||||
@ -85,7 +140,7 @@ impl std::str::FromStr for MultipartRelatedRequest {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing MultipartRelatedRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -132,8 +187,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<MultipartRelatedRequest>> for
|
||||
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 MultipartRelatedRequest - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for MultipartRelatedRequest - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -151,14 +205,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<MultipartRel
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into MultipartRelatedRequest - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into MultipartRelatedRequest - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -168,13 +220,16 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<MultipartRel
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct MultipartRequest {
|
||||
#[serde(rename = "string_field")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub string_field: String,
|
||||
|
||||
#[serde(rename = "optional_string_field")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub optional_string_field: Option<String>,
|
||||
|
||||
#[serde(rename = "object_field")]
|
||||
#[validate(nested)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub object_field: Option<models::MultipartRequestObjectField>,
|
||||
|
||||
@ -254,7 +309,7 @@ impl std::str::FromStr for MultipartRequest {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing MultipartRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -281,7 +336,7 @@ impl std::str::FromStr for MultipartRequest {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing MultipartRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -321,8 +376,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<MultipartRequest>> for Header
|
||||
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 MultipartRequest - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for MultipartRequest - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -340,14 +394,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<MultipartReq
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into MultipartRequest - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into MultipartRequest - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -357,9 +409,11 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<MultipartReq
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct MultipartRequestObjectField {
|
||||
#[serde(rename = "field_a")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub field_a: String,
|
||||
|
||||
#[serde(rename = "field_b")]
|
||||
#[validate(custom(function = "check_xss_vec_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub field_b: Option<Vec<String>>,
|
||||
}
|
||||
@ -430,7 +484,7 @@ impl std::str::FromStr for MultipartRequestObjectField {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing MultipartRequestObjectField".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -473,8 +527,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<MultipartRequestObjectField>>
|
||||
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 MultipartRequestObjectField - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for MultipartRequestObjectField - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -492,14 +545,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<MultipartReq
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into MultipartRequestObjectField - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into MultipartRequestObjectField - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -577,7 +628,7 @@ impl std::str::FromStr for MultipleIdenticalMimeTypesPostRequest {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing MultipleIdenticalMimeTypesPostRequest"
|
||||
.to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -615,10 +666,10 @@ impl std::convert::TryFrom<header::IntoHeaderValue<MultipleIdenticalMimeTypesPos
|
||||
) -> 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 MultipleIdenticalMimeTypesPostRequest - value: {} is invalid {}",
|
||||
hdr_value, e))
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Invalid header value for MultipleIdenticalMimeTypesPostRequest - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -631,17 +682,20 @@ impl std::convert::TryFrom<HeaderValue>
|
||||
|
||||
fn try_from(hdr_value: HeaderValue) -> std::result::Result<Self, Self::Error> {
|
||||
match hdr_value.to_str() {
|
||||
std::result::Result::Ok(value) => {
|
||||
match <MultipleIdenticalMimeTypesPostRequest 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 MultipleIdenticalMimeTypesPostRequest - {}",
|
||||
value, err))
|
||||
std::result::Result::Ok(value) => {
|
||||
match <MultipleIdenticalMimeTypesPostRequest as std::str::FromStr>::from_str(value)
|
||||
{
|
||||
std::result::Result::Ok(value) => {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
},
|
||||
std::result::Result::Err(e) => std::result::Result::Err(
|
||||
format!("Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e))
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header value '{value}' into MultipleIdenticalMimeTypesPostRequest - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -217,3 +217,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -3,7 +3,7 @@ name = "openapi-v3"
|
||||
version = "1.0.7"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "API under test"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
@ -17,6 +17,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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.7
|
||||
- Generator version: 7.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -43,6 +43,14 @@ pub enum EnumInPathPathParamGetResponse {
|
||||
Status200_Success,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[must_use]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum ExamplesTestResponse {
|
||||
/// OK
|
||||
Status200_OK(models::AdditionalPropertiesReferencedAnyOfObject),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[must_use]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
@ -278,6 +286,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// AnyOfGet - GET /any-of
|
||||
async fn any_of_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -287,6 +296,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// CallbackWithHeaderPost - POST /callback-with-header
|
||||
async fn callback_with_header_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -296,6 +306,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// ComplexQueryParamGet - GET /complex-query-param
|
||||
async fn complex_query_param_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -305,17 +316,31 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// EnumInPathPathParamGet - GET /enum_in_path/{path_param}
|
||||
async fn enum_in_path_path_param_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
path_params: &models::EnumInPathPathParamGetPathParams,
|
||||
) -> Result<EnumInPathPathParamGetResponse, E>;
|
||||
|
||||
/// Test examples.
|
||||
///
|
||||
/// ExamplesTest - GET /examples-test
|
||||
async fn examples_test(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
query_params: &models::ExamplesTestQueryParams,
|
||||
) -> Result<ExamplesTestResponse, E>;
|
||||
|
||||
/// Test a Form Post.
|
||||
///
|
||||
/// FormTest - POST /form-test
|
||||
async fn form_test(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -325,6 +350,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// GetWithBooleanParameter - GET /get-with-bool
|
||||
async fn get_with_boolean_parameter(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -334,6 +360,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// JsonComplexQueryParamGet - GET /json-complex-query-param
|
||||
async fn json_complex_query_param_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -343,6 +370,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MandatoryRequestHeaderGet - GET /mandatory-request-header
|
||||
async fn mandatory_request_header_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -352,6 +380,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MergePatchJsonGet - GET /merge-patch-json
|
||||
async fn merge_patch_json_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -362,6 +391,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MultigetGet - GET /multiget
|
||||
async fn multiget_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -370,6 +400,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MultipleAuthSchemeGet - GET /multiple_auth_scheme
|
||||
async fn multiple_auth_scheme_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -378,6 +409,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet - GET /multiple-path-params-with-very-long-path-to-test-formatting/{path_param_a}/{path_param_b}
|
||||
async fn multiple_path_params_with_very_long_path_to_test_formatting_path_param_a_path_param_b_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -387,6 +419,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// OneOfGet - GET /one-of
|
||||
async fn one_of_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -395,6 +428,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// OverrideServerGet - GET /override-server
|
||||
async fn override_server_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -405,6 +439,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// ParamgetGet - GET /paramget
|
||||
async fn paramget_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -414,6 +449,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// ReadonlyAuthSchemeGet - GET /readonly_auth_scheme
|
||||
async fn readonly_auth_scheme_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -422,6 +458,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// RegisterCallbackPost - POST /register-callback
|
||||
async fn register_callback_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -431,6 +468,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// RequiredOctetStreamPut - PUT /required_octet_stream
|
||||
async fn required_octet_stream_put(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -440,6 +478,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// ResponsesWithHeadersGet - GET /responses_with_headers
|
||||
async fn responses_with_headers_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -448,6 +487,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Rfc7807Get - GET /rfc7807
|
||||
async fn rfc7807_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -456,6 +496,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// TwoFirstLetterHeaders - POST /operation-two-first-letter-headers
|
||||
async fn two_first_letter_headers(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -465,6 +506,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// UntypedPropertyGet - GET /untyped_property
|
||||
async fn untyped_property_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -474,6 +516,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// UuidGet - GET /uuid
|
||||
async fn uuid_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -482,6 +525,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// XmlExtraPost - POST /xml_extra
|
||||
async fn xml_extra_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -491,6 +535,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// XmlOtherPost - POST /xml_other
|
||||
async fn xml_other_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -500,6 +545,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// XmlOtherPut - PUT /xml_other
|
||||
async fn xml_other_put(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -511,6 +557,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// XmlPost - POST /xml
|
||||
async fn xml_post(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -520,6 +567,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// XmlPut - PUT /xml
|
||||
async fn xml_put(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -24,6 +24,7 @@ pub trait InfoRepo<E: std::fmt::Debug + Send + Sync + 'static = ()>:
|
||||
/// GetRepoInfo - GET /repos/{repoId}
|
||||
async fn get_repo_info(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -22,6 +22,7 @@ pub trait Repo<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// CreateRepo - POST /repos
|
||||
async fn create_repo(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,60 @@ use validator::Validate;
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct AnyOfGetQueryParams {
|
||||
@ -38,6 +92,15 @@ pub struct EnumInPathPathParamGetPathParams {
|
||||
pub path_param: models::StringEnum,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct ExamplesTestQueryParams {
|
||||
/// A list of IDs to get
|
||||
#[serde(rename = "ids")]
|
||||
#[serde(default)]
|
||||
pub ids: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct GetWithBooleanParameterQueryParams {
|
||||
@ -163,7 +226,9 @@ impl ::std::str::FromStr for AdditionalPropertiesReferencedAnyOfObject {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||
std::result::Result::Err("Parsing additionalProperties for AdditionalPropertiesReferencedAnyOfObject is not supported")
|
||||
std::result::Result::Err(
|
||||
"Parsing additionalProperties for AdditionalPropertiesReferencedAnyOfObject is not supported",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +304,7 @@ pub struct AdditionalPropertiesWithNullable {
|
||||
pub nullable_string: Option<Nullable<String>>,
|
||||
|
||||
#[serde(rename = "nullableMap")]
|
||||
#[validate(custom(function = "check_xss_map_nested"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub nullable_map: Option<std::collections::HashMap<String, models::NullableObject>>,
|
||||
}
|
||||
@ -306,7 +372,7 @@ impl std::str::FromStr for AdditionalPropertiesWithNullable {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing AdditionalPropertiesWithNullable".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -346,10 +412,10 @@ impl std::convert::TryFrom<header::IntoHeaderValue<AdditionalPropertiesWithNulla
|
||||
) -> 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 AdditionalPropertiesWithNullable - value: {} is invalid {}",
|
||||
hdr_value, e))
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Invalid header value for AdditionalPropertiesWithNullable - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -362,17 +428,19 @@ impl std::convert::TryFrom<HeaderValue>
|
||||
|
||||
fn try_from(hdr_value: HeaderValue) -> std::result::Result<Self, Self::Error> {
|
||||
match hdr_value.to_str() {
|
||||
std::result::Result::Ok(value) => {
|
||||
match <AdditionalPropertiesWithNullable 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 AdditionalPropertiesWithNullable - {}",
|
||||
value, err))
|
||||
std::result::Result::Ok(value) => {
|
||||
match <AdditionalPropertiesWithNullable as std::str::FromStr>::from_str(value) {
|
||||
std::result::Result::Ok(value) => {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
},
|
||||
std::result::Result::Err(e) => std::result::Result::Err(
|
||||
format!("Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e))
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header value '{value}' into AdditionalPropertiesWithNullable - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -489,8 +557,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<AnotherXmlArray>> for HeaderV
|
||||
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 AnotherXmlArray - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for AnotherXmlArray - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -508,14 +575,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<AnotherXmlAr
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into AnotherXmlArray - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into AnotherXmlArray - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -574,6 +639,7 @@ impl std::ops::DerefMut for AnotherXmlInner {
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct AnotherXmlObject {
|
||||
#[serde(rename = "inner_string")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub inner_string: Option<String>,
|
||||
}
|
||||
@ -590,10 +656,10 @@ impl AnotherXmlObject {
|
||||
/// Should be implemented in a serde serializer
|
||||
impl std::fmt::Display for AnotherXmlObject {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let params: Vec<Option<String>> = vec![self
|
||||
.inner_string
|
||||
.as_ref()
|
||||
.map(|inner_string| ["inner_string".to_string(), inner_string.to_string()].join(","))];
|
||||
let params: Vec<Option<String>> =
|
||||
vec![self.inner_string.as_ref().map(|inner_string| {
|
||||
["inner_string".to_string(), inner_string.to_string()].join(",")
|
||||
})];
|
||||
|
||||
write!(
|
||||
f,
|
||||
@ -629,7 +695,7 @@ impl std::str::FromStr for AnotherXmlObject {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing AnotherXmlObject".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -643,7 +709,7 @@ impl std::str::FromStr for AnotherXmlObject {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing AnotherXmlObject".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -672,8 +738,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<AnotherXmlObject>> for Header
|
||||
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 AnotherXmlObject - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for AnotherXmlObject - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -691,14 +756,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<AnotherXmlOb
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into AnotherXmlObject - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into AnotherXmlObject - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -797,9 +860,11 @@ impl PartialEq for AnyOfObject {
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct AnyOfProperty {
|
||||
#[serde(rename = "requiredAnyOf")]
|
||||
#[validate(nested)]
|
||||
pub required_any_of: models::AnyOfObject,
|
||||
|
||||
#[serde(rename = "optionalAnyOf")]
|
||||
#[validate(nested)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub optional_any_of: Option<models::Model12345AnyOfObject>,
|
||||
}
|
||||
@ -861,7 +926,7 @@ impl std::str::FromStr for AnyOfProperty {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing AnyOfProperty".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -881,7 +946,7 @@ impl std::str::FromStr for AnyOfProperty {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing AnyOfProperty".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -915,8 +980,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<AnyOfProperty>> for HeaderVal
|
||||
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 AnyOfProperty - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for AnyOfProperty - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -934,14 +998,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<AnyOfPropert
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into AnyOfProperty - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into AnyOfProperty - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -952,10 +1014,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<AnyOfPropert
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct DuplicateXmlObject {
|
||||
#[serde(rename = "inner_string")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub inner_string: Option<String>,
|
||||
|
||||
#[serde(rename = "inner_array")]
|
||||
#[validate(nested)]
|
||||
pub inner_array: models::XmlArray,
|
||||
}
|
||||
|
||||
@ -1016,7 +1080,7 @@ impl std::str::FromStr for DuplicateXmlObject {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing DuplicateXmlObject".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1035,7 +1099,7 @@ impl std::str::FromStr for DuplicateXmlObject {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing DuplicateXmlObject".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1069,8 +1133,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<DuplicateXmlObject>> for Head
|
||||
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 DuplicateXmlObject - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for DuplicateXmlObject - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1088,14 +1151,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<DuplicateXml
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into DuplicateXmlObject - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into DuplicateXmlObject - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1120,6 +1181,12 @@ pub enum EnumWithStarObject {
|
||||
Star,
|
||||
}
|
||||
|
||||
impl validator::Validate for EnumWithStarObject {
|
||||
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for EnumWithStarObject {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
@ -1138,7 +1205,7 @@ impl std::str::FromStr for EnumWithStarObject {
|
||||
"FOO" => std::result::Result::Ok(EnumWithStarObject::Foo),
|
||||
"BAR" => std::result::Result::Ok(EnumWithStarObject::Bar),
|
||||
"*" => std::result::Result::Ok(EnumWithStarObject::Star),
|
||||
_ => std::result::Result::Err(format!("Value not valid: {}", s)),
|
||||
_ => std::result::Result::Err(format!(r#"Value not valid: {s}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1243,6 +1310,7 @@ impl std::ops::DerefMut for Error {
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct FormTestRequest {
|
||||
#[serde(rename = "requiredArray")]
|
||||
#[validate(custom(function = "check_xss_vec_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub required_array: Option<Vec<String>>,
|
||||
}
|
||||
@ -1308,7 +1376,7 @@ impl std::str::FromStr for FormTestRequest {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing FormTestRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1319,12 +1387,12 @@ impl std::str::FromStr for FormTestRequest {
|
||||
return std::result::Result::Err(
|
||||
"Parsing a container in this style is not supported in FormTestRequest"
|
||||
.to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing FormTestRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1353,8 +1421,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<FormTestRequest>> for HeaderV
|
||||
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 FormTestRequest - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for FormTestRequest - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1372,14 +1439,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<FormTestRequ
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into FormTestRequest - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into FormTestRequest - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1418,6 +1483,7 @@ impl PartialEq for Model12345AnyOfObject {
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct MultigetGet201Response {
|
||||
#[serde(rename = "foo")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub foo: Option<String>,
|
||||
}
|
||||
@ -1434,10 +1500,11 @@ impl MultigetGet201Response {
|
||||
/// Should be implemented in a serde serializer
|
||||
impl std::fmt::Display for MultigetGet201Response {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let params: Vec<Option<String>> = vec![self
|
||||
.foo
|
||||
.as_ref()
|
||||
.map(|foo| ["foo".to_string(), foo.to_string()].join(","))];
|
||||
let params: Vec<Option<String>> = vec![
|
||||
self.foo
|
||||
.as_ref()
|
||||
.map(|foo| ["foo".to_string(), foo.to_string()].join(",")),
|
||||
];
|
||||
|
||||
write!(
|
||||
f,
|
||||
@ -1473,7 +1540,7 @@ impl std::str::FromStr for MultigetGet201Response {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing MultigetGet201Response".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1487,7 +1554,7 @@ impl std::str::FromStr for MultigetGet201Response {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing MultigetGet201Response".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1516,8 +1583,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<MultigetGet201Response>> for
|
||||
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 MultigetGet201Response - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for MultigetGet201Response - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1535,14 +1601,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<MultigetGet2
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into MultigetGet201Response - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into MultigetGet201Response - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1695,8 +1759,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<MyIdList>> for HeaderValue {
|
||||
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 MyIdList - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for MyIdList - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1714,14 +1777,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<MyIdList> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into MyIdList - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into MyIdList - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1970,7 +2031,7 @@ impl std::str::FromStr for NullableTest {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing NullableTest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1997,30 +2058,30 @@ impl std::str::FromStr for NullableTest {
|
||||
return std::result::Result::Err(
|
||||
"Parsing a container in this style is not supported in NullableTest"
|
||||
.to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
"min_item_test" => {
|
||||
return std::result::Result::Err(
|
||||
"Parsing a container in this style is not supported in NullableTest"
|
||||
.to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
"max_item_test" => {
|
||||
return std::result::Result::Err(
|
||||
"Parsing a container in this style is not supported in NullableTest"
|
||||
.to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
"min_max_item_test" => {
|
||||
return std::result::Result::Err(
|
||||
"Parsing a container in this style is not supported in NullableTest"
|
||||
.to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing NullableTest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2066,8 +2127,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<NullableTest>> for HeaderValu
|
||||
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 NullableTest - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for NullableTest - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2085,14 +2145,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<NullableTest
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into NullableTest - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into NullableTest - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2173,7 +2231,7 @@ impl std::str::FromStr for ObjectHeader {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing ObjectHeader".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2191,7 +2249,7 @@ impl std::str::FromStr for ObjectHeader {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing ObjectHeader".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2225,8 +2283,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<ObjectHeader>> for HeaderValu
|
||||
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 ObjectHeader - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for ObjectHeader - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2244,14 +2301,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<ObjectHeader
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into ObjectHeader - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into ObjectHeader - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2326,7 +2381,7 @@ impl std::str::FromStr for ObjectParam {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing ObjectParam".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2344,7 +2399,7 @@ impl std::str::FromStr for ObjectParam {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing ObjectParam".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2378,8 +2433,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<ObjectParam>> for HeaderValue
|
||||
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 ObjectParam - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for ObjectParam - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2397,14 +2451,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<ObjectParam>
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into ObjectParam - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into ObjectParam - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2496,7 +2548,7 @@ impl std::str::FromStr for ObjectUntypedProps {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing ObjectUntypedProps".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2550,8 +2602,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<ObjectUntypedProps>> for Head
|
||||
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 ObjectUntypedProps - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for ObjectUntypedProps - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2569,14 +2620,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<ObjectUntype
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into ObjectUntypedProps - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into ObjectUntypedProps - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2586,6 +2635,7 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<ObjectUntype
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct ObjectWithArrayOfObjects {
|
||||
#[serde(rename = "objectArray")]
|
||||
#[validate(nested)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub object_array: Option<Vec<models::StringObject>>,
|
||||
}
|
||||
@ -2648,7 +2698,7 @@ impl std::str::FromStr for ObjectWithArrayOfObjects {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing ObjectWithArrayOfObjects".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2684,8 +2734,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<ObjectWithArrayOfObjects>> fo
|
||||
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 ObjectWithArrayOfObjects - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for ObjectWithArrayOfObjects - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2703,14 +2752,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<ObjectWithAr
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into ObjectWithArrayOfObjects - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into ObjectWithArrayOfObjects - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -2937,6 +2984,12 @@ pub enum StringEnum {
|
||||
Bar,
|
||||
}
|
||||
|
||||
impl validator::Validate for StringEnum {
|
||||
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for StringEnum {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
@ -2953,7 +3006,7 @@ impl std::str::FromStr for StringEnum {
|
||||
match s {
|
||||
"FOO" => std::result::Result::Ok(StringEnum::Foo),
|
||||
"BAR" => std::result::Result::Ok(StringEnum::Bar),
|
||||
_ => std::result::Result::Err(format!("Value not valid: {}", s)),
|
||||
_ => std::result::Result::Err(format!(r#"Value not valid: {s}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3154,8 +3207,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<XmlArray>> for HeaderValue {
|
||||
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 XmlArray - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for XmlArray - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -3173,14 +3225,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<XmlArray> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into XmlArray - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into XmlArray - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -3239,6 +3289,7 @@ impl std::ops::DerefMut for XmlInner {
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct XmlObject {
|
||||
#[serde(rename = "innerString")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub inner_string: Option<String>,
|
||||
|
||||
@ -3310,7 +3361,7 @@ impl std::str::FromStr for XmlObject {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing XmlObject".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -3328,7 +3379,7 @@ impl std::str::FromStr for XmlObject {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing XmlObject".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3358,8 +3409,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<XmlObject>> for HeaderValue {
|
||||
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 XmlObject - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for XmlObject - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -3377,14 +3427,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<XmlObject> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into XmlObject - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into XmlObject - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -38,6 +38,9 @@ where
|
||||
.route("/enum_in_path/{path_param}",
|
||||
get(enum_in_path_path_param_get::<I, A, E>)
|
||||
)
|
||||
.route("/examples-test",
|
||||
get(examples_test::<I, A, E>)
|
||||
)
|
||||
.route("/form-test",
|
||||
post(form_test::<I, A, E>)
|
||||
)
|
||||
@ -422,6 +425,86 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn examples_test_validation(
|
||||
query_params: models::ExamplesTestQueryParams,
|
||||
) -> std::result::Result<(models::ExamplesTestQueryParams,), ValidationErrors> {
|
||||
query_params.validate()?;
|
||||
|
||||
Ok((query_params,))
|
||||
}
|
||||
/// ExamplesTest - GET /examples-test
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn examples_test<I, A, E>(
|
||||
method: Method,
|
||||
host: Host,
|
||||
cookies: CookieJar,
|
||||
QueryExtra(query_params): QueryExtra<models::ExamplesTestQueryParams>,
|
||||
State(api_impl): State<I>,
|
||||
) -> Result<Response, StatusCode>
|
||||
where
|
||||
I: AsRef<A> + Send + Sync,
|
||||
A: apis::default::Default<E> + Send + Sync,
|
||||
E: std::fmt::Debug + Send + Sync + 'static,
|
||||
{
|
||||
let validation = examples_test_validation(query_params);
|
||||
|
||||
let Ok((query_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()
|
||||
.examples_test(&method, &host, &cookies, &query_params)
|
||||
.await;
|
||||
|
||||
let mut response = Response::builder();
|
||||
|
||||
let resp = match result {
|
||||
Ok(rsp) => match rsp {
|
||||
apis::default::ExamplesTestResponse::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(why) => {
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl
|
||||
.as_ref()
|
||||
.handle_error(&method, &host, &cookies, why)
|
||||
.await;
|
||||
}
|
||||
};
|
||||
|
||||
resp.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(validator::Validate)]
|
||||
#[allow(dead_code)]
|
||||
struct FormTestBodyValidator<'a> {
|
||||
@ -645,7 +728,7 @@ where
|
||||
Err(err) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!("Invalid header X-Header - {}", err)))
|
||||
.body(Body::from(format!("Invalid header X-Header - {err}")))
|
||||
.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
@ -1016,9 +1099,9 @@ where
|
||||
},
|
||||
},
|
||||
Err(why) => {
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
},
|
||||
};
|
||||
|
||||
@ -1093,9 +1176,9 @@ where
|
||||
},
|
||||
},
|
||||
Err(why) => {
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
},
|
||||
};
|
||||
|
||||
@ -1355,9 +1438,9 @@ where
|
||||
},
|
||||
},
|
||||
Err(why) => {
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
},
|
||||
};
|
||||
|
||||
@ -1539,7 +1622,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling success_info header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling success_info header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1553,7 +1636,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling bool_header header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling bool_header header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1569,7 +1652,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling object_header header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling object_header header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1611,7 +1694,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling further_info header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling further_info header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1627,7 +1710,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling failure_info header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling failure_info header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1803,7 +1886,7 @@ where
|
||||
Err(err) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!("Invalid header x-header-one - {}", err)))
|
||||
.body(Body::from(format!("Invalid header x-header-one - {err}")))
|
||||
.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
@ -1820,7 +1903,7 @@ where
|
||||
Err(err) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!("Invalid header x-header-two - {}", err)))
|
||||
.body(Body::from(format!("Invalid header x-header-two - {err}")))
|
||||
.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
@ -1932,9 +2015,9 @@ where
|
||||
},
|
||||
},
|
||||
Err(why) => {
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
|
||||
},
|
||||
};
|
||||
|
||||
@ -2511,3 +2594,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -3,7 +3,7 @@ name = "ops-v3"
|
||||
version = "0.0.1"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
@ -17,6 +17,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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: 0.0.1
|
||||
- Generator version: 7.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -310,6 +310,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op10Get - GET /op10
|
||||
async fn op10_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -318,6 +319,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op11Get - GET /op11
|
||||
async fn op11_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -326,6 +328,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op12Get - GET /op12
|
||||
async fn op12_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -334,6 +337,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op13Get - GET /op13
|
||||
async fn op13_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -342,6 +346,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op14Get - GET /op14
|
||||
async fn op14_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -350,6 +355,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op15Get - GET /op15
|
||||
async fn op15_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -358,6 +364,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op16Get - GET /op16
|
||||
async fn op16_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -366,6 +373,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op17Get - GET /op17
|
||||
async fn op17_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -374,6 +382,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op18Get - GET /op18
|
||||
async fn op18_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -382,6 +391,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op19Get - GET /op19
|
||||
async fn op19_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -390,6 +400,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op1Get - GET /op1
|
||||
async fn op1_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -398,6 +409,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op20Get - GET /op20
|
||||
async fn op20_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -406,6 +418,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op21Get - GET /op21
|
||||
async fn op21_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -414,6 +427,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op22Get - GET /op22
|
||||
async fn op22_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -422,6 +436,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op23Get - GET /op23
|
||||
async fn op23_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -430,6 +445,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op24Get - GET /op24
|
||||
async fn op24_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -438,6 +454,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op25Get - GET /op25
|
||||
async fn op25_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -446,6 +463,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op26Get - GET /op26
|
||||
async fn op26_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -454,6 +472,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op27Get - GET /op27
|
||||
async fn op27_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -462,6 +481,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op28Get - GET /op28
|
||||
async fn op28_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -470,6 +490,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op29Get - GET /op29
|
||||
async fn op29_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -478,6 +499,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op2Get - GET /op2
|
||||
async fn op2_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -486,6 +508,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op30Get - GET /op30
|
||||
async fn op30_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -494,6 +517,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op31Get - GET /op31
|
||||
async fn op31_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -502,6 +526,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op32Get - GET /op32
|
||||
async fn op32_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -510,6 +535,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op33Get - GET /op33
|
||||
async fn op33_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -518,6 +544,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op34Get - GET /op34
|
||||
async fn op34_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -526,6 +553,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op35Get - GET /op35
|
||||
async fn op35_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -534,6 +562,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op36Get - GET /op36
|
||||
async fn op36_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -542,6 +571,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op37Get - GET /op37
|
||||
async fn op37_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -550,6 +580,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op3Get - GET /op3
|
||||
async fn op3_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -558,6 +589,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op4Get - GET /op4
|
||||
async fn op4_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -566,6 +598,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op5Get - GET /op5
|
||||
async fn op5_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -574,6 +607,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op6Get - GET /op6
|
||||
async fn op6_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -582,6 +616,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op7Get - GET /op7
|
||||
async fn op7_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -590,6 +625,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op8Get - GET /op8
|
||||
async fn op8_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -598,6 +634,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// Op9Get - GET /op9
|
||||
async fn op9_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,3 +6,57 @@ use validator::Validate;
|
||||
#[cfg(feature = "server")]
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -2132,3 +2132,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -4,7 +4,7 @@ version = "1.0.0"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\"
|
||||
license = "Apache-2.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
publish = ["crates-io"]
|
||||
|
||||
[features]
|
||||
@ -19,6 +19,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ pub trait AnotherFake<E: std::fmt::Debug + Send + Sync + 'static = ()>:
|
||||
/// TestSpecialTags - PATCH /v2/another-fake/dummy
|
||||
async fn test_special_tags(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -124,6 +124,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// Call123example - GET /v2/fake/operation-with-numeric-id
|
||||
async fn call123example(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -132,6 +133,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// FakeOuterBooleanSerialize - POST /v2/fake/outer/boolean
|
||||
async fn fake_outer_boolean_serialize(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -141,6 +143,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// FakeOuterCompositeSerialize - POST /v2/fake/outer/composite
|
||||
async fn fake_outer_composite_serialize(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -150,6 +153,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// FakeOuterNumberSerialize - POST /v2/fake/outer/number
|
||||
async fn fake_outer_number_serialize(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -159,6 +163,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// FakeOuterStringSerialize - POST /v2/fake/outer/string
|
||||
async fn fake_outer_string_serialize(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -168,6 +173,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// FakeResponseWithNumericalDescription - GET /v2/fake/response-with-numerical-description
|
||||
async fn fake_response_with_numerical_description(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -176,6 +182,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// HyphenParam - GET /v2/fake/hyphenParam/{hyphen-param}
|
||||
async fn hyphen_param(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -185,6 +192,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// TestBodyWithQueryParams - PUT /v2/fake/body-with-query-params
|
||||
async fn test_body_with_query_params(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -197,6 +205,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// TestClientModel - PATCH /v2/fake
|
||||
async fn test_client_model(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -208,6 +217,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// TestEndpointParameters - POST /v2/fake
|
||||
async fn test_endpoint_parameters(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -220,6 +230,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// TestEnumParameters - GET /v2/fake
|
||||
async fn test_enum_parameters(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -233,6 +244,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// TestInlineAdditionalProperties - POST /v2/fake/inline-additionalProperties
|
||||
async fn test_inline_additional_properties(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -244,6 +256,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// TestJsonFormData - GET /v2/fake/jsonFormData
|
||||
async fn test_json_form_data(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -26,6 +26,7 @@ pub trait FakeClassnameTags123<E: std::fmt::Debug + Send + Sync + 'static = ()>:
|
||||
/// TestClassname - PATCH /v2/fake_classname_test
|
||||
async fn test_classname(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -94,6 +94,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// AddPet - POST /v2/pet
|
||||
async fn add_pet(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -105,6 +106,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// DeletePet - DELETE /v2/pet/{petId}
|
||||
async fn delete_pet(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -117,6 +119,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// FindPetsByStatus - GET /v2/pet/findByStatus
|
||||
async fn find_pets_by_status(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -128,6 +131,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// FindPetsByTags - GET /v2/pet/findByTags
|
||||
async fn find_pets_by_tags(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -139,6 +143,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// GetPetById - GET /v2/pet/{petId}
|
||||
async fn get_pet_by_id(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -151,6 +156,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// UpdatePet - PUT /v2/pet
|
||||
async fn update_pet(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -162,6 +168,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// UpdatePetWithForm - POST /v2/pet/{petId}
|
||||
async fn update_pet_with_form(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -174,6 +181,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// UploadFile - POST /v2/pet/{petId}/uploadImage
|
||||
async fn upload_file(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -58,6 +58,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// DeleteOrder - DELETE /v2/store/order/{order_id}
|
||||
async fn delete_order(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -69,6 +70,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// GetInventory - GET /v2/store/inventory
|
||||
async fn get_inventory(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -80,6 +82,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// GetOrderById - GET /v2/store/order/{order_id}
|
||||
async fn get_order_by_id(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -91,6 +94,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// PlaceOrder - POST /v2/store/order
|
||||
async fn place_order(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -94,6 +94,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// CreateUser - POST /v2/user
|
||||
async fn create_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -105,6 +106,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// CreateUsersWithArrayInput - POST /v2/user/createWithArray
|
||||
async fn create_users_with_array_input(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -116,6 +118,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// CreateUsersWithListInput - POST /v2/user/createWithList
|
||||
async fn create_users_with_list_input(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -127,6 +130,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// DeleteUser - DELETE /v2/user/{username}
|
||||
async fn delete_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -138,6 +142,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// GetUserByName - GET /v2/user/{username}
|
||||
async fn get_user_by_name(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -149,6 +154,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// LoginUser - GET /v2/user/login
|
||||
async fn login_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -160,6 +166,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// LogoutUser - GET /v2/user/logout
|
||||
async fn logout_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -170,6 +177,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// UpdateUser - PUT /v2/user/{username}
|
||||
async fn update_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -986,10 +986,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1095,8 +1092,7 @@ where
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!(
|
||||
"Invalid header enum_header_string_array - {}",
|
||||
err
|
||||
"Invalid header enum_header_string_array - {err}"
|
||||
)))
|
||||
.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
@ -1115,8 +1111,7 @@ where
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!(
|
||||
"Invalid header enum_header_string - {}",
|
||||
err
|
||||
"Invalid header enum_header_string - {err}"
|
||||
)))
|
||||
.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
@ -1533,7 +1528,7 @@ where
|
||||
Err(err) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!("Invalid header api_key - {}", err)))
|
||||
.body(Body::from(format!("Invalid header api_key - {err}")))
|
||||
.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
@ -1783,10 +1778,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -2192,10 +2184,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -2855,7 +2844,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling x_rate_limit header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling x_rate_limit header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -2872,7 +2861,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling x_expires_after header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling x_expires_after header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -3055,3 +3044,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -4,7 +4,7 @@ version = "1.0.0"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters."
|
||||
license = "Apache-2.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
@ -18,6 +18,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -98,6 +98,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// AddPet - POST /v2/pet
|
||||
async fn add_pet(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -109,6 +110,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// DeletePet - DELETE /v2/pet/{petId}
|
||||
async fn delete_pet(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -121,6 +123,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// FindPetsByStatus - GET /v2/pet/findByStatus
|
||||
async fn find_pets_by_status(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -132,6 +135,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// FindPetsByTags - GET /v2/pet/findByTags
|
||||
async fn find_pets_by_tags(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -143,6 +147,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// GetPetById - GET /v2/pet/{petId}
|
||||
async fn get_pet_by_id(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -155,6 +160,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// UpdatePet - PUT /v2/pet
|
||||
async fn update_pet(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -166,6 +172,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// UpdatePetWithForm - POST /v2/pet/{petId}
|
||||
async fn update_pet_with_form(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -178,6 +185,7 @@ pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHand
|
||||
/// UploadFile - POST /v2/pet/{petId}/uploadImage
|
||||
async fn upload_file(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -58,6 +58,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// DeleteOrder - DELETE /v2/store/order/{orderId}
|
||||
async fn delete_order(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -69,6 +70,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// GetInventory - GET /v2/store/inventory
|
||||
async fn get_inventory(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -80,6 +82,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// GetOrderById - GET /v2/store/order/{orderId}
|
||||
async fn get_order_by_id(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -91,6 +94,7 @@ pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHa
|
||||
/// PlaceOrder - POST /v2/store/order
|
||||
async fn place_order(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -97,6 +97,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// CreateUser - POST /v2/user
|
||||
async fn create_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -109,6 +110,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// CreateUsersWithArrayInput - POST /v2/user/createWithArray
|
||||
async fn create_users_with_array_input(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -121,6 +123,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// CreateUsersWithListInput - POST /v2/user/createWithList
|
||||
async fn create_users_with_list_input(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -133,6 +136,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// DeleteUser - DELETE /v2/user/{username}
|
||||
async fn delete_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -145,6 +149,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// GetUserByName - GET /v2/user/{username}
|
||||
async fn get_user_by_name(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -156,6 +161,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// LoginUser - GET /v2/user/login
|
||||
async fn login_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -167,6 +173,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// LogoutUser - GET /v2/user/logout
|
||||
async fn logout_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
@ -178,6 +185,7 @@ pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
|
||||
/// UpdateUser - PUT /v2/user/{username}
|
||||
async fn update_user(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,60 @@ use validator::Validate;
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct DeletePetHeaderParams {
|
||||
@ -94,7 +148,7 @@ pub struct LoginUserQueryParams {
|
||||
#[serde(rename = "username")]
|
||||
#[validate(
|
||||
regex(path = *RE_LOGINUSERQUERYPARAMS_USERNAME),
|
||||
)]
|
||||
)]
|
||||
pub username: String,
|
||||
/// The password for login in clear text
|
||||
#[serde(rename = "password")]
|
||||
@ -121,10 +175,12 @@ pub struct ApiResponse {
|
||||
pub code: Option<i32>,
|
||||
|
||||
#[serde(rename = "type")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub r#type: Option<String>,
|
||||
|
||||
#[serde(rename = "message")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub message: Option<String>,
|
||||
}
|
||||
@ -193,7 +249,7 @@ impl std::str::FromStr for ApiResponse {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing ApiResponse".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -215,7 +271,7 @@ impl std::str::FromStr for ApiResponse {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing ApiResponse".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,8 +302,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<ApiResponse>> for HeaderValue
|
||||
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 ApiResponse - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for ApiResponse - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -265,14 +320,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<ApiResponse>
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into ApiResponse - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into ApiResponse - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -289,7 +342,8 @@ pub struct Category {
|
||||
#[serde(rename = "name")]
|
||||
#[validate(
|
||||
regex(path = *RE_CATEGORY_NAME),
|
||||
)]
|
||||
custom(function = "check_xss_string"),
|
||||
)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
}
|
||||
@ -357,7 +411,7 @@ impl std::str::FromStr for Category {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing Category".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -375,7 +429,7 @@ impl std::str::FromStr for Category {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing Category".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -405,8 +459,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<Category>> for HeaderValue {
|
||||
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 Category - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for Category - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -424,14 +477,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Category> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into Category - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into Category - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -460,6 +511,7 @@ pub struct Order {
|
||||
/// Order Status
|
||||
/// Note: inline enums are not fully supported by openapi-generator
|
||||
#[serde(rename = "status")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub status: Option<String>,
|
||||
|
||||
@ -545,7 +597,7 @@ impl std::str::FromStr for Order {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing Order".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -580,7 +632,7 @@ impl std::str::FromStr for Order {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing Order".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -614,8 +666,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<Order>> for HeaderValue {
|
||||
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 Order - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for Order - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -632,13 +683,11 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Order> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into Order - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into Order - {err}"#
|
||||
)),
|
||||
},
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -653,22 +702,27 @@ pub struct Pet {
|
||||
pub id: Option<i64>,
|
||||
|
||||
#[serde(rename = "category")]
|
||||
#[validate(nested)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub category: Option<models::Category>,
|
||||
|
||||
#[serde(rename = "name")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
pub name: String,
|
||||
|
||||
#[serde(rename = "photoUrls")]
|
||||
#[validate(custom(function = "check_xss_vec_string"))]
|
||||
pub photo_urls: Vec<String>,
|
||||
|
||||
#[serde(rename = "tags")]
|
||||
#[validate(nested)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tags: Option<Vec<models::Tag>>,
|
||||
|
||||
/// pet status in the store
|
||||
/// Note: inline enums are not fully supported by openapi-generator
|
||||
#[serde(rename = "status")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub status: Option<String>,
|
||||
}
|
||||
@ -750,7 +804,7 @@ impl std::str::FromStr for Pet {
|
||||
let val = match string_iter.next() {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
return std::result::Result::Err("Missing value while parsing Pet".to_string())
|
||||
return std::result::Result::Err("Missing value while parsing Pet".to_string());
|
||||
}
|
||||
};
|
||||
|
||||
@ -773,12 +827,12 @@ impl std::str::FromStr for Pet {
|
||||
"photoUrls" => {
|
||||
return std::result::Result::Err(
|
||||
"Parsing a container in this style is not supported in Pet".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
"tags" => {
|
||||
return std::result::Result::Err(
|
||||
"Parsing a container in this style is not supported in Pet".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
#[allow(clippy::redundant_clone)]
|
||||
"status" => intermediate_rep.status.push(
|
||||
@ -787,7 +841,7 @@ impl std::str::FromStr for Pet {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing Pet".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -827,8 +881,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<Pet>> for HeaderValue {
|
||||
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 Pet - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for Pet - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -845,13 +898,11 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Pet> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into Pet - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into Pet - {err}"#
|
||||
)),
|
||||
},
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -866,6 +917,7 @@ pub struct Tag {
|
||||
pub id: Option<i64>,
|
||||
|
||||
#[serde(rename = "name")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
}
|
||||
@ -927,7 +979,7 @@ impl std::str::FromStr for Tag {
|
||||
let val = match string_iter.next() {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
return std::result::Result::Err("Missing value while parsing Tag".to_string())
|
||||
return std::result::Result::Err("Missing value while parsing Tag".to_string());
|
||||
}
|
||||
};
|
||||
|
||||
@ -945,7 +997,7 @@ impl std::str::FromStr for Tag {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing Tag".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -973,8 +1025,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<Tag>> for HeaderValue {
|
||||
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 Tag - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for Tag - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -991,13 +1042,11 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Tag> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into Tag - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into Tag - {err}"#
|
||||
)),
|
||||
},
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1008,11 +1057,13 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<Tag> {
|
||||
pub struct UpdatePetWithFormRequest {
|
||||
/// Updated name of the pet
|
||||
#[serde(rename = "name")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Updated status of the pet
|
||||
#[serde(rename = "status")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub status: Option<String>,
|
||||
}
|
||||
@ -1076,7 +1127,7 @@ impl std::str::FromStr for UpdatePetWithFormRequest {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing UpdatePetWithFormRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1094,7 +1145,7 @@ impl std::str::FromStr for UpdatePetWithFormRequest {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing UpdatePetWithFormRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1124,8 +1175,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<UpdatePetWithFormRequest>> fo
|
||||
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 UpdatePetWithFormRequest - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for UpdatePetWithFormRequest - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1143,14 +1193,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<UpdatePetWit
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into UpdatePetWithFormRequest - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into UpdatePetWithFormRequest - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1161,6 +1209,7 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<UpdatePetWit
|
||||
pub struct UploadFileRequest {
|
||||
/// Additional data to pass to server
|
||||
#[serde(rename = "additionalMetadata")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub additional_metadata: Option<String>,
|
||||
|
||||
@ -1234,7 +1283,7 @@ impl std::str::FromStr for UploadFileRequest {
|
||||
None => {
|
||||
return std::result::Result::Err(
|
||||
"Missing value while parsing UploadFileRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1252,7 +1301,7 @@ impl std::str::FromStr for UploadFileRequest {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing UploadFileRequest".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1282,8 +1331,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<UploadFileRequest>> for Heade
|
||||
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 UploadFileRequest - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for UploadFileRequest - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1301,14 +1349,12 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<UploadFileRe
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into UploadFileRequest - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into UploadFileRequest - {err}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1323,26 +1369,32 @@ pub struct User {
|
||||
pub id: Option<i64>,
|
||||
|
||||
#[serde(rename = "username")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub username: Option<String>,
|
||||
|
||||
#[serde(rename = "firstName")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub first_name: Option<String>,
|
||||
|
||||
#[serde(rename = "lastName")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub last_name: Option<String>,
|
||||
|
||||
#[serde(rename = "email")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub email: Option<String>,
|
||||
|
||||
#[serde(rename = "password")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub password: Option<String>,
|
||||
|
||||
#[serde(rename = "phone")]
|
||||
#[validate(custom(function = "check_xss_string"))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub phone: Option<String>,
|
||||
|
||||
@ -1439,7 +1491,7 @@ impl std::str::FromStr for User {
|
||||
let val = match string_iter.next() {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
return std::result::Result::Err("Missing value while parsing User".to_string())
|
||||
return std::result::Result::Err("Missing value while parsing User".to_string());
|
||||
}
|
||||
};
|
||||
|
||||
@ -1481,7 +1533,7 @@ impl std::str::FromStr for User {
|
||||
_ => {
|
||||
return std::result::Result::Err(
|
||||
"Unexpected key while parsing User".to_string(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1517,8 +1569,7 @@ impl std::convert::TryFrom<header::IntoHeaderValue<User>> for HeaderValue {
|
||||
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 User - value: {} is invalid {}",
|
||||
hdr_value, e
|
||||
r#"Invalid header value for User - value: {hdr_value} is invalid {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -1535,13 +1586,11 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<User> {
|
||||
std::result::Result::Ok(header::IntoHeaderValue(value))
|
||||
}
|
||||
std::result::Result::Err(err) => std::result::Result::Err(format!(
|
||||
"Unable to convert header value '{}' into User - {}",
|
||||
value, err
|
||||
r#"Unable to convert header value '{value}' into User - {err}"#
|
||||
)),
|
||||
},
|
||||
std::result::Result::Err(e) => std::result::Result::Err(format!(
|
||||
"Unable to convert header: {:?} to string: {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header: {hdr_value:?} to string: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -197,7 +197,7 @@ where
|
||||
Err(err) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from(format!("Invalid header api_key - {}", err)))
|
||||
.body(Body::from(format!("Invalid header api_key - {err}")))
|
||||
.map_err(|e| {
|
||||
error!(error = ?e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
@ -447,10 +447,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -872,10 +869,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1149,10 +1143,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1235,10 +1226,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1322,10 +1310,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1401,10 +1386,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1592,7 +1574,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling set_cookie header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling set_cookie header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1607,7 +1589,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling x_rate_limit header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling x_rate_limit header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1624,7 +1606,7 @@ where
|
||||
Err(e) => {
|
||||
return Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("An internal server error occurred handling x_expires_after header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
.body(Body::from(format!("An internal server error occurred handling x_expires_after header - {e}"))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
|
||||
}
|
||||
};
|
||||
|
||||
@ -1695,10 +1677,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1784,10 +1763,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -1835,3 +1811,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -3,7 +3,7 @@ name = "ping-bearer-auth"
|
||||
version = "1.0.0"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
@ -17,6 +17,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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
|
||||
- Generator version: 7.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// PingGet - GET /ping
|
||||
async fn ping_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,3 +6,57 @@ use validator::Validate;
|
||||
#[cfg(feature = "server")]
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -55,10 +55,7 @@ where
|
||||
.await;
|
||||
let claims = None.or(claims_in_auth_header);
|
||||
let Some(claims) = claims else {
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
|
||||
return response_with_status_code_only(StatusCode::UNAUTHORIZED);
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
@ -102,3 +99,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
@ -3,7 +3,7 @@ name = "rust-axum-array-params-test"
|
||||
version = "0.0.1"
|
||||
authors = ["OpenAPI Generator team and contributors"]
|
||||
description = "No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["server"]
|
||||
@ -17,6 +17,7 @@ conversion = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ammonia = "4"
|
||||
async-trait = "0.1"
|
||||
axum = { version = "0.8", features = ["multipart"] }
|
||||
axum-extra = { version = "0.10", features = ["cookie", "query"] }
|
||||
|
||||
@ -12,7 +12,7 @@ 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: 0.0.1
|
||||
- Generator version: 7.14.0-SNAPSHOT
|
||||
- Generator version: 7.15.0-SNAPSHOT
|
||||
|
||||
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::Error
|
||||
/// EndpointGet - GET /endpoint
|
||||
async fn endpoint_get(
|
||||
&self,
|
||||
|
||||
method: &Method,
|
||||
host: &Host,
|
||||
cookies: &CookieJar,
|
||||
|
||||
@ -31,14 +31,12 @@ macro_rules! ihv_generate {
|
||||
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
|
||||
r#"Unable to parse {} as a string: {e}"#,
|
||||
stringify!($t)
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -82,8 +80,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
|
||||
.collect(),
|
||||
)),
|
||||
Err(e) => Err(format!(
|
||||
"Unable to parse header: {:?} as a string - {}",
|
||||
hdr_value, e
|
||||
r#"Unable to parse header: {hdr_value:?} as a string - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -96,8 +93,7 @@ impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} into a header - {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -111,7 +107,7 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<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)),
|
||||
Err(e) => Err(format!(r#"Unable to convert header {hdr_value:?} to {e}"#)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,7 @@ impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -139,11 +134,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
|
||||
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!(r#"Unable to parse bool from {hdr_value} - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert {:?} from a header {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert {hdr_value:?} from a header {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -156,8 +150,7 @@ impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert: {hdr_value:?} into a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -172,11 +165,10 @@ impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
|
||||
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!(r#"Unable to parse: {hdr_value} as date - {e}"#)),
|
||||
},
|
||||
Err(e) => Err(format!(
|
||||
"Unable to convert header {:?} to string {}",
|
||||
hdr_value, e
|
||||
r#"Unable to convert header {hdr_value:?} to string {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -189,8 +181,7 @@ impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
|
||||
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
|
||||
r#"Unable to convert {hdr_value:?} to a header: {e}"#
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,60 @@ use validator::Validate;
|
||||
use crate::header;
|
||||
use crate::{models, types::*};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
|
||||
if ammonia::is_html(v) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.iter().any(|i| ammonia::is_html(i)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_string(
|
||||
v: &std::collections::HashMap<String, String>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| ammonia::is_html(v)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map_nested<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError>
|
||||
where
|
||||
T: validator::Validate,
|
||||
{
|
||||
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_xss_map<T>(
|
||||
v: &std::collections::HashMap<String, T>,
|
||||
) -> std::result::Result<(), validator::ValidationError> {
|
||||
if v.keys().any(|k| ammonia::is_html(k)) {
|
||||
std::result::Result::Err(validator::ValidationError::new("xss detected"))
|
||||
} else {
|
||||
std::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
|
||||
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
|
||||
pub struct EndpointGetQueryParams {
|
||||
|
||||
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use axum::{body::Body, extract::*, response::Response, routing::*};
|
||||
use axum_extra::extract::{CookieJar, Host, Query as QueryExtra};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header::CONTENT_TYPE};
|
||||
use tracing::error;
|
||||
use validator::{Validate, ValidationErrors};
|
||||
|
||||
@ -88,3 +88,12 @@ where
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn response_with_status_code_only(code: StatusCode) -> Result<Response, StatusCode> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(|_| code)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use base64::{Engine, engine::general_purpose};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@ -661,7 +661,7 @@ impl<T> validator::ValidateEmail for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateEmail,
|
||||
{
|
||||
fn as_email_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_email_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_email_string(),
|
||||
Self::Null => None,
|
||||
@ -673,7 +673,7 @@ impl<T> validator::ValidateUrl for Nullable<T>
|
||||
where
|
||||
T: validator::ValidateUrl,
|
||||
{
|
||||
fn as_url_string(&self) -> Option<std::borrow::Cow<str>> {
|
||||
fn as_url_string(&'_ self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
match self {
|
||||
Self::Present(x) => x.as_url_string(),
|
||||
Self::Null => None,
|
||||
|
||||
@ -1 +1 @@
|
||||
7.14.0-SNAPSHOT
|
||||
7.15.0-SNAPSHOT
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user