Skip to main content

rust_microservice/
settings.rs

1//! The server behavior is fully driven by a YAML configuration file. This file defines network
2//! settings, security providers, data sources, and observability integrations used at runtime.
3//!
4//! The configuration is loaded during application startup and applied automatically by the framework.
5//!
6//! ## Server
7//!
8//! Defines how the HTTP service is exposed and how it interacts with the runtime environment.
9//!
10//! | Field                 | Description                                                               |
11//! | --------------------- | ------------------------------------------------------------------------- |
12//! | `host`                | Network interface where the server binds.                                 |
13//! | `port`                | Main HTTP port used by the API.                                           |
14//! | `health-check-port`   | Dedicated port exposing the health endpoint.                              |
15//! | `use-docker-compose`  | Enables orchestration of dependencies via Docker Compose.                 |
16//! | `docker-compose-file` | Path to the Docker Compose definition used when orchestration is enabled. |
17//!
18//! ## CORS
19//!
20//! Controls cross-origin access policies.
21//!
22//! | Field                     | Description                                                        |
23//! | ------------------------- | ------------------------------------------------------------------ |
24//! | `max-age`                 | Duration (seconds) browsers cache preflight responses.             |
25//! | `allow-credentials`       | Allows cookies and authorization headers in cross-origin requests. |
26//! | `allowed-methods`         | HTTP methods allowed for cross-origin calls.                       |
27//! | `allowed-headers`         | Headers accepted from clients.                                     |
28//! | `allowed-origins_pattern` | Comma-separated list of allowed origin patterns.                   |
29//!
30//! ## Security — OAuth2 / OpenID Connect
31//!
32//! Enables authentication and token validation using an OAuth2 provider.
33//!
34//! | Field                     | Description                                                        |
35//! | ------------------------- | ------------------------------------------------------------------ |
36//! | `enabled`                 | Activates OAuth2 protection for secured endpoints.                 |
37//! | `load-from-discovery-url` | Automatically loads provider metadata from the discovery endpoint. |
38//! | `discovery-url`           | OpenID Provider discovery document.                                |
39//! | `issuer-uri`              | Expected token issuer identifier.                                  |
40//! | `jwks-uri`                | JSON Web Key Set endpoint used to validate tokens.                 |
41//! | `token-uri`               | Endpoint for obtaining access tokens.                              |
42//! | `authorization-uri`       | Authorization endpoint for login flows.                            |
43//! | `introspection-uri`       | Endpoint for validating opaque tokens.                             |
44//! | `user_info-uri`           | Endpoint returning authenticated user claims.                      |
45//! | `end_session-uri`         | Logout endpoint for session termination.                           |
46//!
47//! ## OAuth2 Client
48//!
49//! Credentials used by the server when interacting with the identity provider.
50//!
51//! | Field    | Description                             |
52//! | -------- | --------------------------------------- |
53//! | `id`     | OAuth2 client identifier.               |
54//! | `secret` | OAuth2 client secret.                   |
55//! | `scope`  | Requested scopes during authentication. |
56//!
57//!
58//! ## JWKS
59//!
60//! Defines local JSON Web Keys used for token signing or validation.
61//!
62//! Each key entry contains:
63//!
64//! - kid — Key identifier
65//! - kty — Key type
66//! - alg — Signing algorithm
67//! - use — Key usage
68//! - e — Public exponent
69//! - n — RSA modulus
70//! - x5c — X.509 certificate chain
71//!
72//! This section is typically used when keys are managed internally or cached locally.
73//!
74//! ## Data Sources
75//!
76//! ### *Redis*
77//!
78//! Configuration for distributed cache and key-value storage.
79//!
80//! | Field                  | Description                                     |
81//! | ---------------------- | ----------------------------------------------- |
82//! | `enabled`              | Enables Redis integration.                      |
83//! | `host` / `port`        | Connection settings.                            |
84//! | `client-type`          | Redis client implementation.                    |
85//! | `lettuce.pool`         | Connection pool configuration.                  |
86//! | `repositories.enabled` | Enables repository abstraction backed by Redis. |
87//!
88//!
89//! ### *Relational Databases*
90//!
91//! Defines a list of database connections used by the application.
92//!
93//! Each database entry supports:
94//!
95//! - Connection pooling configuration
96//! - Timeouts and lifecycle settings
97//! - SQL logging control
98//! - Independent enable/disable toggle
99//!
100//! This allows multiple data sources (e.g., API DB, job processing DB) to coexist in the same runtime.
101//!
102//! | Field            | Description                                                                                       |
103//! | ---------------- | ------------------------------------------------------------------------------------------------- |
104//! | `name`           | Logical name of the database connection used by the server.                                       |
105//! | `enabled`        | Enables or disables this database configuration. When `false`, the connection is not initialized. |
106//! | `url`            | Database connection string used to establish the connection.                                      |
107//! | `min-pool-size`  | Minimum number of connections maintained in the pool.                                             |
108//! | `max-pool-size`  | Maximum number of connections allowed in the pool.                                                |
109//! | `logging`        | Enables query and connection logging for this database.                                           |
110//! | `aquire-timeout` | Maximum time (in seconds) to wait when acquiring a connection from the pool.                      |
111//! | `max-lifetime`   | Maximum lifetime (in minutes) of                                                                  |
112//!
113//! > Important: The framework currently supports only SQLite, PostgreSQL, MySQL, MariaDB, and
114//! > Microsoft SQL Server databases.
115//!
116//! ### *BigQuery Database Connection*
117//!
118//! This section defines the configuration parameters required to establish a secure connection
119//! to Google BigQuery, the fully managed data warehouse provided by Google. These settings allow
120//! the server to authenticate, select the target project and dataset, and control execution
121//! behavior for queries. .
122//!
123//! | Field          | Description                                 |
124//! | -------------- | ------------------------------------------- |
125//! | `enabled`      | Enables BigQuery access.                    |
126//! | `print-tables` | Logs available tables during startup.       |
127//! | `region`       | Dataset region.                             |
128//! | `project`      | Google Cloud project identifier.            |
129//! | `credential`   | Base64-encoded service account credentials. |
130//! | `dataset`      | List of datasets used by the application.   |
131//!
132//!
133//! ## Metrics
134//!
135//! Controls application observability and monitoring integration.
136//!
137//! | Field      | Description                             |
138//! | ---------- | --------------------------------------- |
139//! | `enabled`  | Enables metrics collection.             |
140//! | `app-name` | Identifier used when exporting metrics. |
141//!
142//!
143//! ## Runtime Notes
144//!
145//! - Disabled components remain configured but inactive.
146//! - Secrets should be externalized in production environments.
147//! - Configuration values can be overridden via environment variables or CLI parameters.
148//! - The configuration is validated during server startup.
149//!
150use config::{Case, Config, ConfigError, Environment, File, FileFormat};
151use jsonwebtoken::jwk::{Jwk, JwkSet};
152#[allow(unused)]
153use log::LevelFilter;
154use serde::Deserialize;
155
156/// Configuration for enabling or disabling data repositories.
157///
158/// This structure is usually used to control whether repository
159/// layers backed by Redis or other data sources should be enabled.
160#[derive(Debug, Deserialize, Clone)]
161#[serde(rename_all = "kebab-case")]
162pub struct Repositories {
163    /// Enables or disables repositories.
164    pub enabled: Option<bool>,
165}
166
167/// Connection pool configuration.
168///
169/// Defines limits and behavior for resource pooling,
170/// such as database or Redis connections.
171#[derive(Debug, Deserialize, Clone)]
172#[serde(rename_all = "kebab-case")]
173pub struct Pool {
174    /// Enables or disables the connection pool.
175    pub enabled: Option<bool>,
176
177    /// Minimum number of idle connections kept in the pool.
178    pub min_idle: Option<usize>,
179
180    /// Maximum number of idle connections allowed.
181    pub max_idle: Option<usize>,
182
183    /// Maximum number of active connections allowed.
184    pub max_active: Option<usize>,
185}
186
187/// Lettuce client configuration.
188///
189/// Represents advanced Redis client settings,
190/// including connection pool configuration.
191#[derive(Debug, Deserialize, Clone)]
192#[serde(rename_all = "kebab-case")]
193pub struct Lettuce {
194    /// Connection pool configuration for the Lettuce client.
195    pub pool: Option<Pool>,
196}
197
198/// Redis configuration.
199///
200/// Defines connection parameters and client behavior
201/// for Redis-based integrations.
202#[derive(Debug, Deserialize, Clone)]
203#[serde(rename_all = "kebab-case")]
204pub struct Redis {
205    /// Redis server host.
206    pub host: Option<String>,
207
208    /// Redis server port.
209    pub port: Option<u16>,
210
211    /// Type of Redis client implementation.
212    pub client_type: Option<String>,
213
214    /// Lettuce client specific configuration.
215    pub lettuce: Option<Lettuce>,
216
217    /// Repository configuration related to Redis usage.
218    pub repositories: Option<Repositories>,
219}
220
221/// Relational database configuration.
222///
223/// Controls connection details, pooling behavior,
224/// timeouts, and logging options.
225#[derive(Debug, Deserialize, Clone)]
226#[serde(rename_all = "kebab-case")]
227pub struct Database {
228    /// Database connection name.
229    pub name: String,
230
231    /// Database connection enabled. Default true.
232    pub enabled: Option<bool>,
233
234    /// Database connection URL.
235    pub url: Option<String>,
236
237    /// Minimum number of connections in the pool.
238    pub min_pool_size: Option<u32>,
239
240    /// Maximum number of connections in the pool.
241    pub max_pool_size: Option<u32>,
242
243    /// Enables or disables database query logging.
244    pub logging: Option<bool>,
245
246    /// Timeout for acquiring a connection from the pool (in seconds).
247    pub aquire_timeout: Option<u64>,
248
249    /// Maximum lifetime of a connection (in seconds).
250    pub max_lifetime: Option<u64>,
251
252    /// Maximum idle time of a connection (in seconds).
253    pub idle_timeout: Option<u64>,
254
255    /// Timeout for establishing a new connection (in seconds).
256    pub connect_timeout: Option<u64>,
257
258    /// Logging level used by the database layer.
259    pub logging_level: Option<String>,
260}
261
262/// Google BigQuery configuration.
263///
264/// Defines access parameters and datasets used
265/// for analytics and data processing.
266#[derive(Debug, Deserialize, Clone)]
267#[serde(rename_all = "kebab-case")]
268pub struct BigQuery {
269    /// BigQuery connection enabled. Defaults true.
270    pub enabled: Option<bool>,
271
272    /// Enables or disables printing available tables.
273    pub print_tables: Option<bool>,
274
275    /// BigQuery region.
276    pub region: Option<String>,
277
278    /// Google Cloud project identifier.
279    pub project: Option<String>,
280
281    /// Path or identifier for the credential file.
282    pub credential: Option<String>,
283
284    /// List of datasets available for querying.
285    pub dataset: Option<Vec<String>>,
286}
287
288/// Data layer configuration.
289///
290/// Groups all data-related configurations,
291/// such as Redis, BigQuery, and relational databases.
292#[derive(Debug, Deserialize, Clone)]
293#[serde(rename_all = "kebab-case")]
294pub struct Data {
295    /// Enables or disables redis connection.
296    pub enabled: Option<bool>,
297
298    /// Redis configuration.
299    pub redis: Option<Redis>,
300
301    /// BigQuery configuration.
302    pub bigquery: Option<BigQuery>,
303
304    /// Relational database configuration.
305    pub databases: Option<Vec<Database>>,
306}
307
308/// CORS (Cross-Origin Resource Sharing) configuration.
309///
310/// Controls how the server handles cross-origin HTTP requests.
311#[derive(Debug, Deserialize, Clone)]
312#[serde(rename_all = "kebab-case")]
313pub struct Cors {
314    /// Maximum cache age for CORS preflight requests (in seconds).
315    pub max_age: Option<u32>,
316
317    /// Indicates whether credentials are allowed.
318    pub allow_credentials: Option<bool>,
319
320    /// Allowed HTTP methods.
321    pub allowed_methods: Option<String>,
322
323    /// Allowed HTTP headers.
324    pub allowed_headers: Option<String>,
325
326    /// Allowed origin patterns.
327    pub allowed_origins_pattern: Option<String>,
328}
329
330/// Server configuration.
331///
332/// Defines network, runtime, and deployment-related settings.
333#[derive(Debug, Deserialize, Clone)]
334#[serde(rename_all = "kebab-case")]
335pub struct Server {
336    /// Server host address.
337    pub host: Option<String>,
338
339    /// Main server port.
340    pub port: u16,
341
342    /// Port used for health check endpoints.
343    pub health_check_port: u16,
344
345    /// Number of worker threads.
346    pub workers: Option<usize>,
347
348    /// Number of worker threads for health checks.
349    pub health_check_workers: Option<usize>,
350
351    /// Indicates whether Docker Compose is used.
352    pub use_docker_compose: Option<bool>,
353
354    /// Path to the Docker Compose file.
355    pub docker_compose_file: Option<String>,
356
357    /// CORS configuration.
358    pub cors: Option<Cors>,
359}
360
361/// Metrics configuration.
362///
363/// Controls application metrics exposure and identification.
364#[derive(Debug, Deserialize, Clone)]
365#[serde(rename_all = "kebab-case")]
366pub struct Metrics {
367    /// Enables or disables metrics collection.
368    pub enabled: Option<bool>,
369
370    /// Application name used in metrics labels.
371    pub app_name: Option<String>,
372}
373
374/// OAuth2 configuration.
375///
376/// Controls authentication and authorization settings.
377#[derive(Debug, Deserialize, Clone)]
378#[serde(rename_all = "kebab-case")]
379pub struct OAuth2Configuration {
380    /// Enables or disables OAuth2 integration.
381    pub enabled: Option<bool>,
382
383    /// Enables or disables automatic OAuth2 discovery.
384    pub discovery_enabled: Option<bool>,
385
386    /// OAuth2 discovery URL for automatic configuration.
387    #[serde(alias = "discovery_endpoint")]
388    pub discovery_url: Option<String>,
389
390    /// OAuth2 configuration issuer URL.
391    #[serde(alias = "issuer", alias = "issuer_endpoint")]
392    pub issuer_uri: Option<String>,
393
394    /// OAuth2 configuration JSON Web Key Set URI.
395    #[serde(alias = "jwks_endpoint", alias = "jwks_uri")]
396    pub jwks_uri: Option<String>,
397
398    /// OAuth2 configuration token endpoint URI.
399    #[serde(alias = "token_endpoint")]
400    pub token_uri: Option<String>,
401
402    /// OAuth2 configuration authorization endpoint URI.
403    #[serde(alias = "authorization_endpoint")]
404    pub authorization_uri: Option<String>,
405
406    /// OAuth2 configuration introspection endpoint URI.
407    #[serde(alias = "introspection_endpoint")]
408    pub introspection_uri: Option<String>,
409
410    /// OAuth2 configuration user info endpoint URI.
411    #[serde(alias = "userinfo_endpoint")]
412    pub user_info_uri: Option<String>,
413
414    /// OAuth2 configuration end session endpoint URI.
415    #[serde(alias = "end_session_endpoint")]
416    pub end_session_uri: Option<String>,
417
418    /// OAuth2 client configuration.
419    pub client: Option<OAuth2Client>,
420
421    /// OAuth2 JSON Web Key Set. This list of keys is used to validate tokens.
422    pub jwks: Option<JwkSet>,
423}
424
425/// OAuth2 client configuration.
426
427#[derive(Debug, Deserialize, Clone)]
428#[serde(rename_all = "kebab-case")]
429pub struct OAuth2Client {
430    /// OAuth2 client ID.
431    pub id: Option<String>,
432
433    /// OAuth2 client secret.
434    pub secret: Option<String>,
435
436    /// OAuth2 client scopes.
437    pub scope: Option<String>,
438}
439
440/// Server security configuration.
441///
442/// This structure aggregates all security-related settings.
443#[derive(Debug, Deserialize, Clone)]
444#[serde(rename_all = "kebab-case")]
445pub struct Security {
446    /// OAuth2 configuration.
447    pub oauth2: Option<OAuth2Configuration>,
448}
449
450/// Global application settings.
451///
452/// Root configuration structure that aggregates
453/// server, data, and metrics configurations.
454#[derive(Debug, Deserialize, Clone)]
455#[serde(rename_all = "kebab-case")]
456pub struct Settings {
457    /// Server configuration.
458    pub server: Option<Server>,
459
460    /// Data layer configuration.
461    pub data: Option<Data>,
462
463    /// Metrics configuration.
464    pub metrics: Option<Metrics>,
465
466    /// Security configuration.
467    pub security: Option<Security>,
468}
469
470impl Settings {
471    /// Loads the application settings from a configuration file.
472    ///
473    /// This function reads the configuration from the specified file path,
474    /// deserializes it into the `Settings` structure, and returns it.
475    ///
476    /// # Arguments
477    ///
478    /// * `config_path` - A string slice that holds the path to the configuration file.
479    ///
480    /// # Returns
481    ///
482    /// * `Result<Settings, ConfigError>` - The loaded settings or an error if loading fails.
483    pub fn new(config_path: &str) -> Result<Self> {
484        let mut builder = Config::builder().add_source(File::new(config_path, FileFormat::Yaml));
485
486        builder =
487            builder.add_source(Environment::with_convert_case(Case::UpperSnake).separator("_"));
488
489        let config = builder.build()?;
490        config.try_deserialize::<Settings>()
491    }
492
493    /// Returns the OAuth2 configuration object if available.
494    ///
495    /// # Returns
496    ///
497    /// * `Option<OAuth2Configuration>` - The OAuth2 configuration if present, `None` otherwise.
498    pub fn get_oauth2_config(&self) -> Option<OAuth2Configuration> {
499        self.security.as_ref()?.oauth2.clone()
500    }
501
502    /// Returns a JWK (JSON Web Key) object if available for the given kid.
503    ///
504    /// # Arguments
505    ///
506    /// * `kid` - A string slice that holds the key ID of the JWK object.
507    ///
508    /// # Returns
509    ///
510    /// * `Option<Jwk>` - The JWK object if present, `None` otherwise.
511    pub fn get_auth2_public_key(&self, kid: &str) -> Option<Jwk> {
512        self.security
513            .as_ref()?
514            .oauth2
515            .as_ref()?
516            .jwks
517            .as_ref()?
518            .find(kid)
519            .cloned()
520    }
521
522    /// Returns the OAuth2 token endpoint URL if available.
523    ///
524    /// # Returns
525    ///
526    /// * `Option<String>` - The OAuth2 token endpoint URL if present, `None` otherwise.
527    pub fn get_auth2_token_url(&self) -> Option<String> {
528        self.security
529            .as_ref()?
530            .oauth2
531            .as_ref()?
532            .token_uri
533            .as_ref()
534            .cloned()
535    }
536}
537
538/// A type alias for a `Result` with the `ConfigError` error type.
539pub type Result<T, E = ConfigError> = std::result::Result<T, E>;