Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions bin/configs/manual/rust-axum-apikey-authorization.yaml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -286,7 +289,7 @@ public void processOpts() {
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.");
}

Expand Down Expand Up @@ -316,6 +319,24 @@ public void processOpts() {
} 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) {
Expand Down Expand Up @@ -722,6 +743,21 @@ public OperationsMap postProcessOperationsWithModels(final OperationsMap operati
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;
Expand Down Expand Up @@ -982,6 +1018,22 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ description = "{{{.}}}"
{{#licenseInfo}}
license = "{{.}}"
{{/licenseInfo}}
edition = "2021"
edition = "2024"
{{#publishRustRegistry}}
publish = ["{{.}}"]
{{/publishRustRegistry}}
Expand All @@ -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"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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}}
Expand Down
Loading
Loading