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
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,19 @@ homepage = "{{.}}"

[features]
default = ["server"]
server = []
server = [
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
"ammonia",
"async-trait",
"axum",
"axum-extra",
"bytes",
"futures-util",
"headers",
"http",
"serde_html_form",
"tokio",
"tracing",
]
conversion = [
"frunk",
"frunk_derives",
Expand All @@ -39,35 +51,35 @@ conversion = [
]

[dependencies]
ammonia = "4"
async-trait = "0.1"
axum = { version = "0.8", features = ["multipart"] }
ammonia = { version = "4", optional = true }
async-trait = { version = "0.1", optional = true }
axum = { version = "0.8", features = ["multipart"], optional = true }
axum-extra = { version = "0.12", features = [
"cookie",
"query",
"typed-header",
] }
], optional = true }
base64 = "0.22"
bytes = "1"
bytes = { version = "1", optional = true }
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 }
futures-util = "0.3"
headers = "0.4"
http = "1"
futures-util = { version = "0.3", optional = true }
headers = { version = "0.4", optional = true }
http = { version = "1", optional = true }
lazy_static = "1"
regex = "1"
serde = { version = "1", features = ["derive"] }
serde_html_form = "0.2"
serde_html_form = { version = "0.2", optional = true }
serde_json = { version = "1", features = ["raw_value"] }
tokio = { version = "1", default-features = false, features = [
"signal",
"rt-multi-thread",
] }
tracing = { version = "0.1", features = ["attributes"] }
], optional = true }
tracing = { version = "0.1", features = ["attributes"], optional = true }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.20", features = ["derive"] }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The generated library has a few optional features that can be activated through
* `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.
* Disabling it (`default-features = false`) leaves only `models` and `types`, without Axum, Tokio or other server dependencies (including `ammonia`, so the XSS check in model validation is skipped), e.g. for sharing the models with a WASM frontend.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
clippy::too_many_arguments
)]

#[cfg(feature = "server")]
extern crate futures_util;

pub const BASE_PATH: &str = "{{{basePathWithoutHost}}}";
Expand All @@ -26,6 +27,7 @@ pub mod server;

pub mod models;
pub mod types;
#[cfg(feature = "server")]
pub mod apis;

#[cfg(feature = "server")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#![allow(unused_qualifications)]

#[cfg(feature = "server")]
use http::HeaderValue;
use validator::Validate;

#[cfg(feature = "server")]
use crate::header;
use crate::{models, types::*};

#[cfg(feature = "server")]
#[allow(dead_code)]
pub type SSE = std::pin::Pin<std::boxed::Box<dyn futures_util::Stream<Item = std::result::Result<axum::response::sse::Event, std::convert::Infallible>> + std::marker::Send + std::marker::Sync>>;

Expand All @@ -17,9 +19,21 @@ fn from_validation_error(e: validator::ValidationError) -> validator::Validation
errs
}

/// XSS detection relies on `ammonia`, which is only pulled in by the `server` feature.
/// Without it (e.g. models-only WASM builds), values are never flagged as HTML.
#[cfg(feature = "server")]
fn contains_html(v: &str) -> bool {
ammonia::is_html(v)
}

#[cfg(not(feature = "server"))]
fn contains_html(_v: &str) -> bool {
false
}

#[allow(dead_code)]
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
if ammonia::is_html(v) {
if contains_html(v) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -28,7 +42,7 @@ pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::Validatio

#[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)) {
if v.iter().any(|i| contains_html(i)) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -39,7 +53,7 @@ pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::
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)) {
if v.keys().any(|k| contains_html(k)) || v.values().any(|v| contains_html(v)) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -53,7 +67,7 @@ pub fn check_xss_map_nested<T>(
where
T: validator::Validate,
{
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
if v.keys().any(|k| contains_html(k)) || v.values().any(|v| v.validate().is_err()) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -62,7 +76,7 @@ where

#[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)) {
if v.keys().any(|k| contains_html(k)) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,19 @@ homepage = "https://github.com/openapitools/openapi-generator"

[features]
default = ["server"]
server = []
server = [
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
"ammonia",
"async-trait",
"axum",
"axum-extra",
"bytes",
"futures-util",
"headers",
"http",
"serde_html_form",
"tokio",
"tracing",
]
conversion = [
"frunk",
"frunk_derives",
Expand All @@ -18,35 +30,35 @@ conversion = [
]

[dependencies]
ammonia = "4"
async-trait = "0.1"
axum = { version = "0.8", features = ["multipart"] }
ammonia = { version = "4", optional = true }
async-trait = { version = "0.1", optional = true }
axum = { version = "0.8", features = ["multipart"], optional = true }
axum-extra = { version = "0.12", features = [
"cookie",
"query",
"typed-header",
] }
], optional = true }
base64 = "0.22"
bytes = "1"
bytes = { version = "1", optional = true }
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 }
futures-util = "0.3"
headers = "0.4"
http = "1"
futures-util = { version = "0.3", optional = true }
headers = { version = "0.4", optional = true }
http = { version = "1", optional = true }
lazy_static = "1"
regex = "1"
serde = { version = "1", features = ["derive"] }
serde_html_form = "0.2"
serde_html_form = { version = "0.2", optional = true }
serde_json = { version = "1", features = ["raw_value"] }
tokio = { version = "1", default-features = false, features = [
"signal",
"rt-multi-thread",
] }
tracing = { version = "0.1", features = ["attributes"] }
], optional = true }
tracing = { version = "0.1", features = ["attributes"], optional = true }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.20", features = ["derive"] }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ The generated library has a few optional features that can be activated through
* `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.
* Disabling it (`default-features = false`) leaves only `models` and `types`, without Axum, Tokio or other server dependencies (including `ammonia`, so the XSS check in model validation is skipped), e.g. for sharing the models with a WASM frontend.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
clippy::too_many_arguments
)]

#[cfg(feature = "server")]
extern crate futures_util;

pub const BASE_PATH: &str = "/v71";
Expand All @@ -22,6 +23,7 @@ pub const API_VERSION: &str = "1.0.0";
#[cfg(feature = "server")]
pub mod server;

#[cfg(feature = "server")]
pub mod apis;
pub mod models;
pub mod types;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#![allow(unused_qualifications)]

#[cfg(feature = "server")]
use http::HeaderValue;
use validator::Validate;

#[cfg(feature = "server")]
use crate::header;
use crate::{models, types::*};

#[cfg(feature = "server")]
#[allow(dead_code)]
pub type SSE = std::pin::Pin<
std::boxed::Box<
Expand All @@ -24,9 +26,21 @@ fn from_validation_error(e: validator::ValidationError) -> validator::Validation
errs
}

/// XSS detection relies on `ammonia`, which is only pulled in by the `server` feature.
/// Without it (e.g. models-only WASM builds), values are never flagged as HTML.
#[cfg(feature = "server")]
fn contains_html(v: &str) -> bool {
ammonia::is_html(v)
}

#[cfg(not(feature = "server"))]
fn contains_html(_v: &str) -> bool {
false
}

#[allow(dead_code)]
pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::ValidationError> {
if ammonia::is_html(v) {
if contains_html(v) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -35,7 +49,7 @@ pub fn check_xss_string(v: &str) -> std::result::Result<(), validator::Validatio

#[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)) {
if v.iter().any(|i| contains_html(i)) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -46,7 +60,7 @@ pub fn check_xss_vec_string(v: &[String]) -> std::result::Result<(), validator::
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)) {
if v.keys().any(|k| contains_html(k)) || v.values().any(|v| contains_html(v)) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -60,7 +74,7 @@ pub fn check_xss_map_nested<T>(
where
T: validator::Validate,
{
if v.keys().any(|k| ammonia::is_html(k)) || v.values().any(|v| v.validate().is_err()) {
if v.keys().any(|k| contains_html(k)) || v.values().any(|v| v.validate().is_err()) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand All @@ -71,7 +85,7 @@ where
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)) {
if v.keys().any(|k| contains_html(k)) {
std::result::Result::Err(validator::ValidationError::new("xss detected"))
} else {
std::result::Result::Ok(())
Expand Down
36 changes: 24 additions & 12 deletions samples/server/petstore/rust-axum/output/apikey-auths/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,19 @@ homepage = "https://github.com/openapitools/openapi-generator"

[features]
default = ["server"]
server = []
server = [
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
"ammonia",
"async-trait",
"axum",
"axum-extra",
"bytes",
"futures-util",
"headers",
"http",
"serde_html_form",
"tokio",
"tracing",
]
conversion = [
"frunk",
"frunk_derives",
Expand All @@ -18,35 +30,35 @@ conversion = [
]

[dependencies]
ammonia = "4"
async-trait = "0.1"
axum = { version = "0.8", features = ["multipart"] }
ammonia = { version = "4", optional = true }
async-trait = { version = "0.1", optional = true }
axum = { version = "0.8", features = ["multipart"], optional = true }
axum-extra = { version = "0.12", features = [
"cookie",
"query",
"typed-header",
] }
], optional = true }
base64 = "0.22"
bytes = "1"
bytes = { version = "1", optional = true }
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 }
futures-util = "0.3"
headers = "0.4"
http = "1"
futures-util = { version = "0.3", optional = true }
headers = { version = "0.4", optional = true }
http = { version = "1", optional = true }
lazy_static = "1"
regex = "1"
serde = { version = "1", features = ["derive"] }
serde_html_form = "0.2"
serde_html_form = { version = "0.2", optional = true }
serde_json = { version = "1", features = ["raw_value"] }
tokio = { version = "1", default-features = false, features = [
"signal",
"rt-multi-thread",
] }
tracing = { version = "0.1", features = ["attributes"] }
], optional = true }
tracing = { version = "0.1", features = ["attributes"], optional = true }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.20", features = ["derive"] }

Expand Down
Loading
Loading