Skip to main content

api_gateway/
config.rs

1use serde::{Deserialize, Serialize};
2
3fn default_require_auth_by_default() -> bool {
4    true
5}
6
7fn default_body_limit_bytes() -> usize {
8    16 * 1024 * 1024
9}
10
11/// API gateway configuration - reused from `api_gateway` module
12#[derive(Debug, Clone, Deserialize, Serialize, Default)]
13#[serde(deny_unknown_fields)]
14#[allow(clippy::struct_excessive_bools)]
15pub struct ApiGatewayConfig {
16    pub bind_addr: String,
17    #[serde(default)]
18    pub enable_docs: bool,
19    #[serde(default)]
20    pub cors_enabled: bool,
21    /// Optional detailed CORS configuration
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub cors: Option<CorsConfig>,
24
25    /// `OpenAPI` document metadata
26    #[serde(default)]
27    pub openapi: OpenApiConfig,
28
29    /// Global defaults
30    #[serde(default)]
31    pub defaults: Defaults,
32
33    /// Disable authentication and authorization completely.
34    /// When true, middleware automatically injects a default `SecurityContext` for all requests,
35    /// providing access with no tenant filtering.
36    /// This bypasses all tenant isolation and should only be used for single-user on-premise installations.
37    /// Default: false (authentication required via `AuthN` Resolver).
38    #[serde(default)]
39    pub auth_disabled: bool,
40
41    /// If true, routes without explicit security requirement still require authentication (AuthN-only).
42    #[serde(default = "default_require_auth_by_default")]
43    pub require_auth_by_default: bool,
44}
45
46#[derive(Debug, Clone, Deserialize, Serialize)]
47#[serde(deny_unknown_fields, default)]
48pub struct Defaults {
49    /// Fallback rate limit when operation does not specify one
50    pub rate_limit: RateLimitDefaults,
51    /// Global request body size limit in bytes
52    pub body_limit_bytes: usize,
53}
54
55impl Default for Defaults {
56    fn default() -> Self {
57        Self {
58            rate_limit: RateLimitDefaults::default(),
59            body_limit_bytes: default_body_limit_bytes(),
60        }
61    }
62}
63
64#[derive(Debug, Clone, Deserialize, Serialize)]
65#[serde(deny_unknown_fields, default)]
66pub struct RateLimitDefaults {
67    pub rps: u32,
68    pub burst: u32,
69    pub in_flight: u32,
70}
71
72impl Default for RateLimitDefaults {
73    fn default() -> Self {
74        Self {
75            rps: 50,
76            burst: 100,
77            in_flight: 64,
78        }
79    }
80}
81
82#[derive(Debug, Clone, Deserialize, Serialize)]
83#[serde(deny_unknown_fields, default)]
84pub struct CorsConfig {
85    /// Allowed origins: `["*"]` means any
86    pub allowed_origins: Vec<String>,
87    /// Allowed HTTP methods, e.g. `["GET","POST","OPTIONS","PUT","DELETE","PATCH"]`
88    pub allowed_methods: Vec<String>,
89    /// Allowed request headers; `["*"]` means any
90    pub allowed_headers: Vec<String>,
91    /// Whether to allow credentials
92    pub allow_credentials: bool,
93    /// Max age for preflight caching in seconds
94    pub max_age_seconds: u64,
95}
96
97impl Default for CorsConfig {
98    fn default() -> Self {
99        Self {
100            allowed_origins: vec!["*".to_owned()],
101            allowed_methods: vec![
102                "GET".to_owned(),
103                "POST".to_owned(),
104                "PUT".to_owned(),
105                "PATCH".to_owned(),
106                "DELETE".to_owned(),
107                "OPTIONS".to_owned(),
108            ],
109            allowed_headers: vec!["*".to_owned()],
110            allow_credentials: false,
111            max_age_seconds: 600,
112        }
113    }
114}
115
116/// `OpenAPI` document metadata configuration
117#[derive(Debug, Clone, Deserialize, Serialize)]
118#[serde(deny_unknown_fields, default)]
119pub struct OpenApiConfig {
120    /// API title shown in `OpenAPI` documentation
121    pub title: String,
122    /// API version
123    pub version: String,
124    /// API description (optional)
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub description: Option<String>,
127}
128
129impl Default for OpenApiConfig {
130    fn default() -> Self {
131        Self {
132            title: "API Documentation".to_owned(),
133            version: "0.1.0".to_owned(),
134            description: None,
135        }
136    }
137}