Skip to content

Commit

Permalink
Added environment variable support to configs.
Browse files Browse the repository at this point in the history
  • Loading branch information
wyatt-herkamp committed Dec 6, 2024
1 parent f08441d commit a667bfa
Show file tree
Hide file tree
Showing 16 changed files with 938 additions and 278 deletions.
345 changes: 236 additions & 109 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ md-5 = "0.10"
sha1 = "0.10"
sha2 = "0.10"
sha3 = "0.10"
clap = { version = "4", features = ["derive"] }

[workspace.dependencies.sqlx]
version = "0.8"
default-features = false
Expand Down
1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ tracing-subscriber = { version = "0.3", features = [
"json",
], optional = true }
tracing-appender = { version = "0.2", optional = true }
clap.workspace = true
[features]
default = ["migrations", "testing"]
migrations = []
Expand Down
110 changes: 110 additions & 0 deletions crates/core/src/database/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use serde::{Deserialize, Serialize};
use sqlx::postgres::PgConnectOptions;

use super::DBError;

/// The configuration for the database.
///
/// Currently only supports PostgreSQL.
#[derive(Debug, Clone, Deserialize, Serialize, clap::Args)]
#[serde(default)]
pub struct DatabaseConfig {
/// The username to connect to the database.
///
/// Default is `postgres`.
/// Environment_variable: NITRO-REPO_DATABASE_USER
#[clap(long = "database-user", default_value = "postgres")]
pub user: String,
/// The password to connect to the database.
///
/// Default is `password`.
/// Environment_variable: NITRO-REPO_DATABASE_PASSWORD
#[clap(long = "database-password", default_value = "password")]
pub password: String,
#[clap(long = "database-name", default_value = "nitro_repo")]
#[serde(alias = "name")]
pub database: String,
// The host can be in the format host:port or just host.
#[clap(long = "database-host", default_value = "localhost:5432")]
pub host: String,
// The port is optional. If not specified the default port is used. or will be extracted from the host.
#[clap(long = "database-port")]
pub port: Option<u16>,
}
impl DatabaseConfig {
/// Returns the host and port
///
/// If it is not specified in the port field it will attempt to extract it from the host field.
pub fn host_name_port(&self) -> Result<(&str, u16), DBError> {
if let Some(port) = self.port {
Ok((self.host.as_str(), port))
} else {
// The port can be specified in the host field. If it is, we need to extract it.
let host = self.host.split(':').collect::<Vec<&str>>();

match host.len() {
// The port is not specified. Use the default port.
1 => Ok((host[0], 5432)),
// The port is specified within the host. The port option is ignored.
2 => Ok((host[0], host[1].parse::<u16>().unwrap_or(5432))),
_ => {
// Not in the format host:port. Possibly IPv6 but we don't support that.
// If it is IPv6 please specify the port separately.
return Err(DBError::InvalidHost(self.host.clone()));
}
}
}
}
}

impl Default for DatabaseConfig {
fn default() -> Self {
Self {
user: "postgres".to_string(),
password: "password".to_string(),
database: "nitro_repo".to_string(),
host: "localhost".to_string(),
port: Some(5432),
}
}
}
impl TryFrom<DatabaseConfig> for PgConnectOptions {
type Error = DBError;
fn try_from(settings: DatabaseConfig) -> Result<PgConnectOptions, Self::Error> {
let (host, port) = settings.host_name_port()?;
let options = PgConnectOptions::new()
.username(&settings.user)
.password(&settings.password)
.host(host)
.port(port)
.database(&settings.database);

Ok(options)
}
}

#[cfg(test)]
mod tests {

use super::*;

#[test]
fn test_host_name_port() {
{
let config = DatabaseConfig::default();
let (host, port) = config.host_name_port().unwrap();
assert_eq!(host, "localhost");
assert_eq!(port, 5432);
}
{
let config = DatabaseConfig {
host: "localhost:5433".to_string(),
port: None,
..DatabaseConfig::default()
};
let (host, port) = config.host_name_port().unwrap();
assert_eq!(host, "localhost");
assert_eq!(port, 5433);
}
}
}
14 changes: 14 additions & 0 deletions crates/core/src/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,18 @@ pub mod repository;
pub mod storage;
pub mod user;
pub type DateTime = chrono::DateTime<chrono::FixedOffset>;
mod config;
pub mod stages;
pub use config::*;

#[derive(thiserror::Error, Debug)]
pub enum DBError {
#[error(transparent)]
Sqlx(#[from] sqlx::Error),
#[error(transparent)]
Migration(#[from] sqlx::migrate::MigrateError),
#[error("{0}")]
Other(&'static str),
#[error("Invalid host must be in the format host:port got `{0}`")]
InvalidHost(String),
}
1 change: 1 addition & 0 deletions crates/core/src/testing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ impl TestInfoEntry {

#[cfg(test)]
mod tests {
#[ignore = "Requires a database"]
#[tokio::test]
pub async fn test_test_core() {
let (core, entry) = super::TestCore::new(format!("{}::test_test_core", module_path!()))
Expand Down
5 changes: 4 additions & 1 deletion nitro_repo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ sqlx.workspace = true
# Serde
serde.workspace = true
serde_json.workspace = true
serde-env = "0.2"

toml.workspace = true
# utils
futures.workspace = true
Expand Down Expand Up @@ -65,7 +67,7 @@ derive_more.workspace = true
# Badge Stuff
badge-maker.workspace = true
pin-project = "1"
clap = { version = "4", features = ["derive"] }
clap.workspace = true
semver = { version = "1", features = ["std", "serde"] }

# Staging
Expand Down Expand Up @@ -101,6 +103,7 @@ lettre = { version = "0.11.9", features = [
"tokio1-rustls-tls",
], default-features = false }
url = "2"
inquire = "0.7"
[features]
default = ["utoipa-scalar"]
builtin_frontend = []
Expand Down
3 changes: 1 addition & 2 deletions nitro_repo/src/app/authentication/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ impl Debug for SessionManager {
}
}
impl SessionManager {
pub fn new(session_config: Option<SessionManagerConfig>, mode: Mode) -> Result<Self, Error> {
let session_config = session_config.unwrap_or_default();
pub fn new(session_config: SessionManagerConfig, mode: Mode) -> Result<Self, Error> {
let sessions = if session_config.database_location.exists() {
let database = Database::open(&session_config.database_location)?;
if mode == Mode::Debug {
Expand Down
Loading

0 comments on commit a667bfa

Please sign in to comment.