[Rust-Axum][Breaking Changes] Extracting Claims in Cookie/Header (#20097)

* [Rust-Axum][Breaking Changes] Extracting Claims in Cookie/Header

* Update

* Update
This commit is contained in:
Linh Tran Tuan 2024-11-14 15:05:30 +09:00 committed by GitHub
parent 975f4d4679
commit ee698f1e6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 332 additions and 241 deletions

View File

@ -84,6 +84,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
// Grouping (Method, Operation) by Path.
private final Map<String, ArrayList<MethodOperation>> pathMethodOpMap = new HashMap<>();
private boolean havingAuthMethods = false;
// Logger
private final Logger LOGGER = LoggerFactory.getLogger(RustAxumServerCodegen.class);
@ -595,21 +596,26 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
@Override
public OperationsMap postProcessOperationsWithModels(final OperationsMap operationsMap, List<ModelMap> allModels) {
OperationMap operations = operationsMap.getOperations();
final OperationMap operations = operationsMap.getOperations();
operations.put("classnamePascalCase", camelize(operations.getClassname()));
List<CodegenOperation> operationList = operations.getOperation();
for (CodegenOperation op : operationList) {
postProcessOperationWithModels(op);
final boolean hasAuthMethod = operations.getOperation().stream()
.map(this::postProcessOperationWithModels)
.reduce(false, (a, b) -> a || b);
if (hasAuthMethod) {
operations.put("havingAuthMethod", true);
operations.getOperation().forEach(op -> op.vendorExtensions.put("havingAuthMethod", true));
this.havingAuthMethods = true;
}
return operationsMap;
}
private void postProcessOperationWithModels(final CodegenOperation op) {
private boolean postProcessOperationWithModels(final CodegenOperation op) {
boolean consumesJson = false;
boolean consumesPlainText = false;
boolean consumesFormUrlEncoded = false;
boolean hasAuthMethod = false;
if (op.consumes != null) {
for (Map<String, String> consume : op.consumes) {
@ -666,17 +672,20 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
for (CodegenSecurity s : op.authMethods) {
if (s.isApiKey && (s.isKeyInCookie || s.isKeyInHeader)) {
if (s.isKeyInCookie) {
op.vendorExtensions.put("x-has-cookie-auth-methods", "true");
op.vendorExtensions.put("x-api-key-cookie-name", toModelName(s.keyParamName));
op.vendorExtensions.put("x-has-cookie-auth-methods", true);
op.vendorExtensions.put("x-api-key-cookie-name", s.keyParamName);
} else {
op.vendorExtensions.put("x-has-header-auth-methods", "true");
op.vendorExtensions.put("x-api-key-header-name", toModelName(s.keyParamName));
op.vendorExtensions.put("x-has-header-auth-methods", true);
op.vendorExtensions.put("x-api-key-header-name", s.keyParamName);
}
op.vendorExtensions.put("x-has-auth-methods", "true");
op.vendorExtensions.put("x-has-auth-methods", true);
hasAuthMethod = true;
}
}
}
return hasAuthMethod;
}
@Override
@ -772,6 +781,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
.sorted(Comparator.comparing(a -> a.path))
.collect(Collectors.toList());
bundle.put("pathMethodOps", pathMethodOps);
if (havingAuthMethods) bundle.put("havingAuthMethods", true);
return super.postProcessSupportingFileData(bundle);
}

View File

@ -40,7 +40,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -62,7 +62,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -8,14 +8,22 @@ pub mod {{classFilename}};
{{#isApiKey}}
{{#isKeyInCookie}}
/// Cookie Authentication.
#[async_trait::async_trait]
pub trait CookieAuthentication {
fn extract_token_from_cookie(&self, cookies: &axum_extra::extract::CookieJar, key: &str) -> Option<String>;
type Claims;
/// Extracting Claims from Cookie. Return None if the Claims is invalid.
async fn extract_claims_from_cookie(&self, cookies: &axum_extra::extract::CookieJar, key: &str) -> Option<Self::Claims>;
}
{{/isKeyInCookie}}
{{#isKeyInHeader}}
/// API Key Authentication - Header.
#[async_trait::async_trait]
pub trait ApiKeyAuthHeader {
fn extract_token_from_header(&self, headers: &axum::http::header::HeaderMap, key: &str) -> Option<String>;
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
async fn extract_claims_from_header(&self, headers: &axum::http::header::HeaderMap, key: &str) -> Option<Self::Claims>;
}
{{/isKeyInHeader}}
{{/isApiKey}}

View File

@ -18,6 +18,10 @@ use crate::{models, types::*};
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait {{classnamePascalCase}} {
{{#havingAuthMethod}}
type Claims;
{{/havingAuthMethod}}
{{#operation}}
{{#summary}}
/// {{{.}}}.
@ -31,12 +35,9 @@ pub trait {{classnamePascalCase}} {
host: Host,
cookies: CookieJar,
{{#vendorExtensions}}
{{#x-has-cookie-auth-methods}}
token_in_cookie: Option<String>,
{{/x-has-cookie-auth-methods}}
{{#x-has-header-auth-methods}}
token_in_header: Option<String>,
{{/x-has-header-auth-methods}}
{{#x-has-auth-methods}}
claims: Self::Claims,
{{/x-has-auth-methods}}
{{/vendorExtensions}}
{{#headerParams.size}}
header_params: models::{{{operationIdCamelCase}}}HeaderParams,

View File

@ -1,6 +1,6 @@
/// {{{operationId}}} - {{{httpMethod}}} {{{basePathWithoutHost}}}{{{path}}}
#[tracing::instrument(skip_all)]
async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A>(
async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A{{#havingAuthMethod}}, C{{/havingAuthMethod}}>(
method: Method,
host: Host,
cookies: CookieJar,
@ -54,25 +54,33 @@ async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::{{classFilename}}::{{classnamePascalCase}}{{#vendorExtensions}}{{#x-has-cookie-auth-methods}}+ apis::CookieAuthentication{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}+ apis::ApiKeyAuthHeader{{/x-has-header-auth-methods}}{{/vendorExtensions}},
A: apis::{{classFilename}}::{{classnamePascalCase}}{{#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}}{{/vendorExtensions}},
{
{{#vendorExtensions}}
{{#x-has-auth-methods}}
// Authentication
{{/x-has-auth-methods}}
{{#x-has-cookie-auth-methods}}
let token_in_cookie = api_impl.as_ref().extract_token_from_cookie(&cookies, "{{x-api-key-cookie-name}}");
let claims_in_cookie = api_impl.as_ref().extract_claims_from_cookie(&cookies, "{{x-api-key-cookie-name}}").await;
{{/x-has-cookie-auth-methods}}
{{#x-has-header-auth-methods}}
let token_in_header = api_impl.as_ref().extract_token_from_header(&headers, "{{x-api-key-header-name}}");
let claims_in_header = api_impl.as_ref().extract_claims_from_header(&headers, "{{x-api-key-header-name}}").await;
{{/x-has-header-auth-methods}}
{{#x-has-auth-methods}}
if let ({{#x-has-cookie-auth-methods}}None,{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}None,{{/x-has-header-auth-methods}}) = ({{#x-has-cookie-auth-methods}}&token_in_cookie,{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}&token_in_header,{{/x-has-header-auth-methods}}) {
let claims = None
{{#x-has-cookie-auth-methods}}
.or(claims_in_cookie)
{{/x-has-cookie-auth-methods}}
{{#x-has-header-auth-methods}}
.or(claims_in_header)
{{/x-has-header-auth-methods}}
;
let Some(claims) = claims else {
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
}
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
};
{{/x-has-auth-methods}}
{{/vendorExtensions}}
@ -182,12 +190,9 @@ where
host,
cookies,
{{#vendorExtensions}}
{{#x-has-cookie-auth-methods}}
token_in_cookie,
{{/x-has-cookie-auth-methods}}
{{#x-has-header-auth-methods}}
token_in_header,
{{/x-has-header-auth-methods}}
{{#x-has-auth-methods}}
claims,
{{/x-has-auth-methods}}
{{/vendorExtensions}}
{{#headerParams.size}}
header_params,

View File

@ -1,14 +1,15 @@
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A{{#havingAuthMethods}}, C{{/havingAuthMethods}}>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: {{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}} + {{/operations}}{{/apis}}{{/apiInfo}}{{#authMethods}}{{#isApiKey}}{{#isKeyInCookie}}apis::CookieAuthentication + {{/isKeyInCookie}}{{#isKeyInHeader}}apis::ApiKeyAuthHeader + {{/isKeyInHeader}}{{/isApiKey}}{{/authMethods}}'static,
A: {{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}}{{#havingAuthMethod}}<Claims = C>{{/havingAuthMethod}} + {{/operations}}{{/apis}}{{/apiInfo}}{{#authMethods}}{{#isApiKey}}{{#isKeyInCookie}}apis::CookieAuthentication<Claims = C> + {{/isKeyInCookie}}{{#isKeyInHeader}}apis::ApiKeyAuthHeader<Claims = C> + {{/isKeyInHeader}}{{/isApiKey}}{{/authMethods}}'static,
{{#havingAuthMethods}}C: Send + Sync + 'static,{{/havingAuthMethods}}
{
// build our application with a route
Router::new()
{{#pathMethodOps}}
.route("{{{basePathWithoutHost}}}{{{path}}}",
{{#methodOperations}}{{{method}}}({{{operationID}}}::<I, A>){{^-last}}.{{/-last}}{{/methodOperations}}
{{#methodOperations}}{{{method}}}({{{operationID}}}::<I, A{{#vendorExtensions}}{{#havingAuthMethod}}, C{{/havingAuthMethod}}{{/vendorExtensions}}>){{^-last}}.{{/-last}}{{/methodOperations}}
)
{{/pathMethodOps}}
.with_state(api_impl)

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -1,18 +1,26 @@
pub mod payments;
/// API Key Authentication - Header.
#[async_trait::async_trait]
pub trait ApiKeyAuthHeader {
fn extract_token_from_header(
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
async fn extract_claims_from_header(
&self,
headers: &axum::http::header::HeaderMap,
key: &str,
) -> Option<String>;
) -> Option<Self::Claims>;
}
/// Cookie Authentication.
#[async_trait::async_trait]
pub trait CookieAuthentication {
fn extract_token_from_cookie(
type Claims;
/// Extracting Claims from Cookie. Return None if the Claims is invalid.
async fn extract_claims_from_cookie(
&self,
cookies: &axum_extra::extract::CookieJar,
key: &str,
) -> Option<String>;
) -> Option<Self::Claims>;
}

View File

@ -39,6 +39,8 @@ pub enum PostMakePaymentResponse {
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Payments {
type Claims;
/// Get payment method by id.
///
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
@ -68,7 +70,7 @@ pub trait Payments {
method: Method,
host: Host,
cookies: CookieJar,
token_in_cookie: Option<String>,
claims: Self::Claims,
body: Option<models::Payment>,
) -> Result<PostMakePaymentResponse, ()>;
}

View File

@ -13,19 +13,23 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, C>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::payments::Payments + apis::ApiKeyAuthHeader + apis::CookieAuthentication + 'static,
A: apis::payments::Payments<Claims = C>
+ apis::ApiKeyAuthHeader<Claims = C>
+ apis::CookieAuthentication<Claims = C>
+ 'static,
C: Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/v71/paymentMethods", get(get_payment_methods::<I, A>))
.route("/v71/paymentMethods", get(get_payment_methods::<I, A, C>))
.route(
"/v71/paymentMethods/:id",
get(get_payment_method_by_id::<I, A>),
get(get_payment_method_by_id::<I, A, C>),
)
.route("/v71/payments", post(post_make_payment::<I, A>))
.route("/v71/payments", post(post_make_payment::<I, A, C>))
.with_state(api_impl)
}
@ -39,7 +43,7 @@ fn get_payment_method_by_id_validation(
}
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
#[tracing::instrument(skip_all)]
async fn get_payment_method_by_id<I, A>(
async fn get_payment_method_by_id<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -48,7 +52,7 @@ async fn get_payment_method_by_id<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments,
A: apis::payments::Payments<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -138,7 +142,7 @@ fn get_payment_methods_validation() -> std::result::Result<(), ValidationErrors>
}
/// GetPaymentMethods - GET /v71/paymentMethods
#[tracing::instrument(skip_all)]
async fn get_payment_methods<I, A>(
async fn get_payment_methods<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -146,7 +150,7 @@ async fn get_payment_methods<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments,
A: apis::payments::Payments<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_payment_methods_validation())
@ -226,7 +230,7 @@ fn post_make_payment_validation(
}
/// PostMakePayment - POST /v71/payments
#[tracing::instrument(skip_all)]
async fn post_make_payment<I, A>(
async fn post_make_payment<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -235,18 +239,20 @@ async fn post_make_payment<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments + apis::CookieAuthentication,
A: apis::payments::Payments<Claims = C> + apis::CookieAuthentication<Claims = C>,
{
// Authentication
let token_in_cookie = api_impl
let claims_in_cookie = api_impl
.as_ref()
.extract_token_from_cookie(&cookies, "XApiKey");
if let (None,) = (&token_in_cookie,) {
.extract_claims_from_cookie(&cookies, "X-API-Key")
.await;
let claims = None.or(claims_in_cookie);
let Some(claims) = claims else {
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || post_make_payment_validation(body))
@ -262,7 +268,7 @@ where
let result = api_impl
.as_ref()
.post_make_payment(method, host, cookies, token_in_cookie, body)
.post_make_payment(method, host, cookies, claims, body)
.await;
let mut response = Response::builder();

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -20,7 +20,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -42,7 +42,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -6,10 +6,14 @@ pub mod store;
pub mod user;
/// API Key Authentication - Header.
#[async_trait::async_trait]
pub trait ApiKeyAuthHeader {
fn extract_token_from_header(
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
async fn extract_claims_from_header(
&self,
headers: &axum::http::header::HeaderMap,
key: &str,
) -> Option<String>;
) -> Option<Self::Claims>;
}

View File

@ -87,6 +87,8 @@ pub enum UploadFileResponse {
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Pet {
type Claims;
/// Add a new pet to the store.
///
/// AddPet - POST /v2/pet
@ -140,7 +142,7 @@ pub trait Pet {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
path_params: models::GetPetByIdPathParams,
) -> Result<GetPetByIdResponse, ()>;

View File

@ -51,6 +51,8 @@ pub enum PlaceOrderResponse {
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Store {
type Claims;
/// Delete purchase order by ID.
///
/// DeleteOrder - DELETE /v2/store/order/{order_id}
@ -70,7 +72,7 @@ pub trait Store {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
) -> Result<GetInventoryResponse, ()>;
/// Find purchase order by ID.

View File

@ -13,17 +13,18 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, C>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::another_fake::AnotherFake
+ apis::fake::Fake
+ apis::fake_classname_tags123::FakeClassnameTags123
+ apis::pet::Pet
+ apis::store::Store
+ apis::pet::Pet<Claims = C>
+ apis::store::Store<Claims = C>
+ apis::user::User
+ apis::ApiKeyAuthHeader
+ apis::ApiKeyAuthHeader<Claims = C>
+ 'static,
C: Send + Sync + 'static,
{
// build our application with a route
Router::new()
@ -72,21 +73,24 @@ where
get(fake_response_with_numerical_description::<I, A>),
)
.route("/v2/fake_classname_test", patch(test_classname::<I, A>))
.route("/v2/pet", post(add_pet::<I, A>).put(update_pet::<I, A>))
.route(
"/v2/pet",
post(add_pet::<I, A, C>).put(update_pet::<I, A, C>),
)
.route(
"/v2/pet/:pet_id",
delete(delete_pet::<I, A>)
.get(get_pet_by_id::<I, A>)
.post(update_pet_with_form::<I, A>),
delete(delete_pet::<I, A, C>)
.get(get_pet_by_id::<I, A, C>)
.post(update_pet_with_form::<I, A, C>),
)
.route("/v2/pet/:pet_id/uploadImage", post(upload_file::<I, A>))
.route("/v2/pet/findByStatus", get(find_pets_by_status::<I, A>))
.route("/v2/pet/findByTags", get(find_pets_by_tags::<I, A>))
.route("/v2/store/inventory", get(get_inventory::<I, A>))
.route("/v2/store/order", post(place_order::<I, A>))
.route("/v2/pet/:pet_id/uploadImage", post(upload_file::<I, A, C>))
.route("/v2/pet/findByStatus", get(find_pets_by_status::<I, A, C>))
.route("/v2/pet/findByTags", get(find_pets_by_tags::<I, A, C>))
.route("/v2/store/inventory", get(get_inventory::<I, A, C>))
.route("/v2/store/order", post(place_order::<I, A, C>))
.route(
"/v2/store/order/:order_id",
delete(delete_order::<I, A>).get(get_order_by_id::<I, A>),
delete(delete_order::<I, A, C>).get(get_order_by_id::<I, A, C>),
)
.route("/v2/user", post(create_user::<I, A>))
.route(
@ -1340,7 +1344,7 @@ fn add_pet_validation(body: models::Pet) -> std::result::Result<(models::Pet,),
}
/// AddPet - POST /v2/pet
#[tracing::instrument(skip_all)]
async fn add_pet<I, A>(
async fn add_pet<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1349,7 +1353,7 @@ async fn add_pet<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || add_pet_validation(body))
@ -1402,7 +1406,7 @@ fn delete_pet_validation(
}
/// DeletePet - DELETE /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn delete_pet<I, A>(
async fn delete_pet<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1412,7 +1416,7 @@ async fn delete_pet<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
// Header parameters
let header_params = {
@ -1489,7 +1493,7 @@ fn find_pets_by_status_validation(
}
/// FindPetsByStatus - GET /v2/pet/findByStatus
#[tracing::instrument(skip_all)]
async fn find_pets_by_status<I, A>(
async fn find_pets_by_status<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1498,7 +1502,7 @@ async fn find_pets_by_status<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -1566,7 +1570,7 @@ fn find_pets_by_tags_validation(
}
/// FindPetsByTags - GET /v2/pet/findByTags
#[tracing::instrument(skip_all)]
async fn find_pets_by_tags<I, A>(
async fn find_pets_by_tags<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1575,7 +1579,7 @@ async fn find_pets_by_tags<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -1643,7 +1647,7 @@ fn get_pet_by_id_validation(
}
/// GetPetById - GET /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn get_pet_by_id<I, A>(
async fn get_pet_by_id<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1653,18 +1657,20 @@ async fn get_pet_by_id<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet + apis::ApiKeyAuthHeader,
A: apis::pet::Pet<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_pet_by_id_validation(path_params))
@ -1680,7 +1686,7 @@ where
let result = api_impl
.as_ref()
.get_pet_by_id(method, host, cookies, token_in_header, path_params)
.get_pet_by_id(method, host, cookies, claims, path_params)
.await;
let mut response = Response::builder();
@ -1743,7 +1749,7 @@ fn update_pet_validation(
}
/// UpdatePet - PUT /v2/pet
#[tracing::instrument(skip_all)]
async fn update_pet<I, A>(
async fn update_pet<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1752,7 +1758,7 @@ async fn update_pet<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || update_pet_validation(body))
@ -1829,7 +1835,7 @@ fn update_pet_with_form_validation(
}
/// UpdatePetWithForm - POST /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn update_pet_with_form<I, A>(
async fn update_pet_with_form<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1839,7 +1845,7 @@ async fn update_pet_with_form<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -1891,7 +1897,7 @@ fn upload_file_validation(
}
/// UploadFile - POST /v2/pet/{petId}/uploadImage
#[tracing::instrument(skip_all)]
async fn upload_file<I, A>(
async fn upload_file<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1901,7 +1907,7 @@ async fn upload_file<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || upload_file_validation(path_params))
@ -1971,7 +1977,7 @@ fn delete_order_validation(
}
/// DeleteOrder - DELETE /v2/store/order/{order_id}
#[tracing::instrument(skip_all)]
async fn delete_order<I, A>(
async fn delete_order<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1980,7 +1986,7 @@ async fn delete_order<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store,
A: apis::store::Store<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || delete_order_validation(path_params))
@ -2031,7 +2037,7 @@ fn get_inventory_validation() -> std::result::Result<(), ValidationErrors> {
}
/// GetInventory - GET /v2/store/inventory
#[tracing::instrument(skip_all)]
async fn get_inventory<I, A>(
async fn get_inventory<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -2040,18 +2046,20 @@ async fn get_inventory<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store + apis::ApiKeyAuthHeader,
A: apis::store::Store<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_inventory_validation())
@ -2067,7 +2075,7 @@ where
let result = api_impl
.as_ref()
.get_inventory(method, host, cookies, token_in_header)
.get_inventory(method, host, cookies, claims)
.await;
let mut response = Response::builder();
@ -2121,7 +2129,7 @@ fn get_order_by_id_validation(
}
/// GetOrderById - GET /v2/store/order/{order_id}
#[tracing::instrument(skip_all)]
async fn get_order_by_id<I, A>(
async fn get_order_by_id<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -2130,7 +2138,7 @@ async fn get_order_by_id<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store,
A: apis::store::Store<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_order_by_id_validation(path_params))
@ -2209,7 +2217,7 @@ fn place_order_validation(
}
/// PlaceOrder - POST /v2/store/order
#[tracing::instrument(skip_all)]
async fn place_order<I, A>(
async fn place_order<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -2218,7 +2226,7 @@ async fn place_order<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store,
A: apis::store::Store<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || place_order_validation(body))

View File

@ -19,7 +19,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -41,7 +41,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -3,10 +3,14 @@ pub mod store;
pub mod user;
/// API Key Authentication - Header.
#[async_trait::async_trait]
pub trait ApiKeyAuthHeader {
fn extract_token_from_header(
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
async fn extract_claims_from_header(
&self,
headers: &axum::http::header::HeaderMap,
key: &str,
) -> Option<String>;
) -> Option<Self::Claims>;
}

View File

@ -91,6 +91,8 @@ pub enum UploadFileResponse {
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Pet {
type Claims;
/// Add a new pet to the store.
///
/// AddPet - POST /v2/pet
@ -144,7 +146,7 @@ pub trait Pet {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
path_params: models::GetPetByIdPathParams,
) -> Result<GetPetByIdResponse, ()>;

View File

@ -51,6 +51,8 @@ pub enum PlaceOrderResponse {
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Store {
type Claims;
/// Delete purchase order by ID.
///
/// DeleteOrder - DELETE /v2/store/order/{orderId}
@ -70,7 +72,7 @@ pub trait Store {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
) -> Result<GetInventoryResponse, ()>;
/// Find purchase order by ID.

View File

@ -90,6 +90,8 @@ pub enum UpdateUserResponse {
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait User {
type Claims;
/// Create user.
///
/// CreateUser - POST /v2/user
@ -98,7 +100,7 @@ pub trait User {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
body: models::User,
) -> Result<CreateUserResponse, ()>;
@ -110,7 +112,7 @@ pub trait User {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
body: Vec<models::User>,
) -> Result<CreateUsersWithArrayInputResponse, ()>;
@ -122,7 +124,7 @@ pub trait User {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
body: Vec<models::User>,
) -> Result<CreateUsersWithListInputResponse, ()>;
@ -134,7 +136,7 @@ pub trait User {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
path_params: models::DeleteUserPathParams,
) -> Result<DeleteUserResponse, ()>;
@ -168,7 +170,7 @@ pub trait User {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
) -> Result<LogoutUserResponse, ()>;
/// Updated user.
@ -179,7 +181,7 @@ pub trait User {
method: Method,
host: Host,
cookies: CookieJar,
token_in_header: Option<String>,
claims: Self::Claims,
path_params: models::UpdateUserPathParams,
body: models::User,
) -> Result<UpdateUserResponse, ()>;

View File

@ -13,46 +13,54 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, C>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::pet::Pet + apis::store::Store + apis::user::User + apis::ApiKeyAuthHeader + 'static,
A: apis::pet::Pet<Claims = C>
+ apis::store::Store<Claims = C>
+ apis::user::User<Claims = C>
+ apis::ApiKeyAuthHeader<Claims = C>
+ 'static,
C: Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/v2/pet", post(add_pet::<I, A>).put(update_pet::<I, A>))
.route(
"/v2/pet",
post(add_pet::<I, A, C>).put(update_pet::<I, A, C>),
)
.route(
"/v2/pet/:pet_id",
delete(delete_pet::<I, A>)
.get(get_pet_by_id::<I, A>)
.post(update_pet_with_form::<I, A>),
delete(delete_pet::<I, A, C>)
.get(get_pet_by_id::<I, A, C>)
.post(update_pet_with_form::<I, A, C>),
)
.route("/v2/pet/:pet_id/uploadImage", post(upload_file::<I, A>))
.route("/v2/pet/findByStatus", get(find_pets_by_status::<I, A>))
.route("/v2/pet/findByTags", get(find_pets_by_tags::<I, A>))
.route("/v2/store/inventory", get(get_inventory::<I, A>))
.route("/v2/store/order", post(place_order::<I, A>))
.route("/v2/pet/:pet_id/uploadImage", post(upload_file::<I, A, C>))
.route("/v2/pet/findByStatus", get(find_pets_by_status::<I, A, C>))
.route("/v2/pet/findByTags", get(find_pets_by_tags::<I, A, C>))
.route("/v2/store/inventory", get(get_inventory::<I, A, C>))
.route("/v2/store/order", post(place_order::<I, A, C>))
.route(
"/v2/store/order/:order_id",
delete(delete_order::<I, A>).get(get_order_by_id::<I, A>),
delete(delete_order::<I, A, C>).get(get_order_by_id::<I, A, C>),
)
.route("/v2/user", post(create_user::<I, A>))
.route("/v2/user", post(create_user::<I, A, C>))
.route(
"/v2/user/:username",
delete(delete_user::<I, A>)
.get(get_user_by_name::<I, A>)
.put(update_user::<I, A>),
delete(delete_user::<I, A, C>)
.get(get_user_by_name::<I, A, C>)
.put(update_user::<I, A, C>),
)
.route(
"/v2/user/createWithArray",
post(create_users_with_array_input::<I, A>),
post(create_users_with_array_input::<I, A, C>),
)
.route(
"/v2/user/createWithList",
post(create_users_with_list_input::<I, A>),
post(create_users_with_list_input::<I, A, C>),
)
.route("/v2/user/login", get(login_user::<I, A>))
.route("/v2/user/logout", get(logout_user::<I, A>))
.route("/v2/user/login", get(login_user::<I, A, C>))
.route("/v2/user/logout", get(logout_user::<I, A, C>))
.with_state(api_impl)
}
@ -72,7 +80,7 @@ fn add_pet_validation(body: models::Pet) -> std::result::Result<(models::Pet,),
}
/// AddPet - POST /v2/pet
#[tracing::instrument(skip_all)]
async fn add_pet<I, A>(
async fn add_pet<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -81,7 +89,7 @@ async fn add_pet<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || add_pet_validation(body))
@ -150,7 +158,7 @@ fn delete_pet_validation(
}
/// DeletePet - DELETE /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn delete_pet<I, A>(
async fn delete_pet<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -160,7 +168,7 @@ async fn delete_pet<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
// Header parameters
let header_params = {
@ -237,7 +245,7 @@ fn find_pets_by_status_validation(
}
/// FindPetsByStatus - GET /v2/pet/findByStatus
#[tracing::instrument(skip_all)]
async fn find_pets_by_status<I, A>(
async fn find_pets_by_status<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -246,7 +254,7 @@ async fn find_pets_by_status<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -314,7 +322,7 @@ fn find_pets_by_tags_validation(
}
/// FindPetsByTags - GET /v2/pet/findByTags
#[tracing::instrument(skip_all)]
async fn find_pets_by_tags<I, A>(
async fn find_pets_by_tags<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -323,7 +331,7 @@ async fn find_pets_by_tags<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -391,7 +399,7 @@ fn get_pet_by_id_validation(
}
/// GetPetById - GET /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn get_pet_by_id<I, A>(
async fn get_pet_by_id<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -401,18 +409,20 @@ async fn get_pet_by_id<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet + apis::ApiKeyAuthHeader,
A: apis::pet::Pet<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_pet_by_id_validation(path_params))
@ -428,7 +438,7 @@ where
let result = api_impl
.as_ref()
.get_pet_by_id(method, host, cookies, token_in_header, path_params)
.get_pet_by_id(method, host, cookies, claims, path_params)
.await;
let mut response = Response::builder();
@ -491,7 +501,7 @@ fn update_pet_validation(
}
/// UpdatePet - PUT /v2/pet
#[tracing::instrument(skip_all)]
async fn update_pet<I, A>(
async fn update_pet<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -500,7 +510,7 @@ async fn update_pet<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || update_pet_validation(body))
@ -593,7 +603,7 @@ fn update_pet_with_form_validation(
}
/// UpdatePetWithForm - POST /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn update_pet_with_form<I, A>(
async fn update_pet_with_form<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -603,7 +613,7 @@ async fn update_pet_with_form<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -655,7 +665,7 @@ fn upload_file_validation(
}
/// UploadFile - POST /v2/pet/{petId}/uploadImage
#[tracing::instrument(skip_all)]
async fn upload_file<I, A>(
async fn upload_file<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -665,7 +675,7 @@ async fn upload_file<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet,
A: apis::pet::Pet<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || upload_file_validation(path_params))
@ -735,7 +745,7 @@ fn delete_order_validation(
}
/// DeleteOrder - DELETE /v2/store/order/{orderId}
#[tracing::instrument(skip_all)]
async fn delete_order<I, A>(
async fn delete_order<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -744,7 +754,7 @@ async fn delete_order<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store,
A: apis::store::Store<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || delete_order_validation(path_params))
@ -795,7 +805,7 @@ fn get_inventory_validation() -> std::result::Result<(), ValidationErrors> {
}
/// GetInventory - GET /v2/store/inventory
#[tracing::instrument(skip_all)]
async fn get_inventory<I, A>(
async fn get_inventory<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -804,18 +814,20 @@ async fn get_inventory<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store + apis::ApiKeyAuthHeader,
A: apis::store::Store<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_inventory_validation())
@ -831,7 +843,7 @@ where
let result = api_impl
.as_ref()
.get_inventory(method, host, cookies, token_in_header)
.get_inventory(method, host, cookies, claims)
.await;
let mut response = Response::builder();
@ -885,7 +897,7 @@ fn get_order_by_id_validation(
}
/// GetOrderById - GET /v2/store/order/{orderId}
#[tracing::instrument(skip_all)]
async fn get_order_by_id<I, A>(
async fn get_order_by_id<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -894,7 +906,7 @@ async fn get_order_by_id<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store,
A: apis::store::Store<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_order_by_id_validation(path_params))
@ -973,7 +985,7 @@ fn place_order_validation(
}
/// PlaceOrder - POST /v2/store/order
#[tracing::instrument(skip_all)]
async fn place_order<I, A>(
async fn place_order<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -982,7 +994,7 @@ async fn place_order<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store,
A: apis::store::Store<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || place_order_validation(body))
@ -1057,7 +1069,7 @@ fn create_user_validation(
}
/// CreateUser - POST /v2/user
#[tracing::instrument(skip_all)]
async fn create_user<I, A>(
async fn create_user<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1067,18 +1079,20 @@ async fn create_user<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User + apis::ApiKeyAuthHeader,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || create_user_validation(body))
@ -1094,7 +1108,7 @@ where
let result = api_impl
.as_ref()
.create_user(method, host, cookies, token_in_header, body)
.create_user(method, host, cookies, claims, body)
.await;
let mut response = Response::builder();
@ -1137,7 +1151,7 @@ fn create_users_with_array_input_validation(
}
/// CreateUsersWithArrayInput - POST /v2/user/createWithArray
#[tracing::instrument(skip_all)]
async fn create_users_with_array_input<I, A>(
async fn create_users_with_array_input<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1147,18 +1161,20 @@ async fn create_users_with_array_input<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User + apis::ApiKeyAuthHeader,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation =
@ -1175,7 +1191,7 @@ where
let result = api_impl
.as_ref()
.create_users_with_array_input(method, host, cookies, token_in_header, body)
.create_users_with_array_input(method, host, cookies, claims, body)
.await;
let mut response = Response::builder();
@ -1218,7 +1234,7 @@ fn create_users_with_list_input_validation(
}
/// CreateUsersWithListInput - POST /v2/user/createWithList
#[tracing::instrument(skip_all)]
async fn create_users_with_list_input<I, A>(
async fn create_users_with_list_input<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1228,18 +1244,20 @@ async fn create_users_with_list_input<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User + apis::ApiKeyAuthHeader,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation =
@ -1256,7 +1274,7 @@ where
let result = api_impl
.as_ref()
.create_users_with_list_input(method, host, cookies, token_in_header, body)
.create_users_with_list_input(method, host, cookies, claims, body)
.await;
let mut response = Response::builder();
@ -1291,7 +1309,7 @@ fn delete_user_validation(
}
/// DeleteUser - DELETE /v2/user/{username}
#[tracing::instrument(skip_all)]
async fn delete_user<I, A>(
async fn delete_user<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1301,18 +1319,20 @@ async fn delete_user<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User + apis::ApiKeyAuthHeader,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || delete_user_validation(path_params))
@ -1328,7 +1348,7 @@ where
let result = api_impl
.as_ref()
.delete_user(method, host, cookies, token_in_header, path_params)
.delete_user(method, host, cookies, claims, path_params)
.await;
let mut response = Response::builder();
@ -1367,7 +1387,7 @@ fn get_user_by_name_validation(
}
/// GetUserByName - GET /v2/user/{username}
#[tracing::instrument(skip_all)]
async fn get_user_by_name<I, A>(
async fn get_user_by_name<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1376,7 +1396,7 @@ async fn get_user_by_name<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User,
A: apis::user::User<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_user_by_name_validation(path_params))
@ -1447,7 +1467,7 @@ fn login_user_validation(
}
/// LoginUser - GET /v2/user/login
#[tracing::instrument(skip_all)]
async fn login_user<I, A>(
async fn login_user<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1456,7 +1476,7 @@ async fn login_user<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User,
A: apis::user::User<Claims = C>,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || login_user_validation(query_params))
@ -1572,7 +1592,7 @@ fn logout_user_validation() -> std::result::Result<(), ValidationErrors> {
}
/// LogoutUser - GET /v2/user/logout
#[tracing::instrument(skip_all)]
async fn logout_user<I, A>(
async fn logout_user<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1581,18 +1601,20 @@ async fn logout_user<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User + apis::ApiKeyAuthHeader,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || logout_user_validation())
@ -1608,7 +1630,7 @@ where
let result = api_impl
.as_ref()
.logout_user(method, host, cookies, token_in_header)
.logout_user(method, host, cookies, claims)
.await;
let mut response = Response::builder();
@ -1653,7 +1675,7 @@ fn update_user_validation(
}
/// UpdateUser - PUT /v2/user/{username}
#[tracing::instrument(skip_all)]
async fn update_user<I, A>(
async fn update_user<I, A, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1664,18 +1686,20 @@ async fn update_user<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User + apis::ApiKeyAuthHeader,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
{
// Authentication
let token_in_header = api_impl
let claims_in_header = api_impl
.as_ref()
.extract_token_from_header(&headers, "ApiKey");
if let (None,) = (&token_in_header,) {
.extract_claims_from_header(&headers, "api_key")
.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);
}
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || update_user_validation(path_params, body))
@ -1691,7 +1715,7 @@ where
let result = api_impl
.as_ref()
.update_user(method, host, cookies, token_in_header, path_params, body)
.update_user(method, host, cookies, claims, path_params, body)
.await;
let mut response = Response::builder();

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -18,7 +18,7 @@ conversion = [
[dependencies]
async-trait = "0.1"
axum = { version = "0.7" }
axum = "0.7"
axum-extra = { version = "0.9", features = ["cookie", "multipart"] }
base64 = "0.22"
bytes = "1"
@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.18", features = ["derive"] }
validator = { version = "0.19", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"