Compare commits

...

3 Commits

Author SHA1 Message Date
af1aafbde6 Write config to log
All checks were successful
Push Workflows / rustfmt (push) Successful in 6s
Push Workflows / tailwind-build (push) Successful in 6s
Push Workflows / docs (push) Successful in 19s
Push Workflows / clippy (push) Successful in 17s
Push Workflows / test (push) Successful in 24s
Push Workflows / build (push) Successful in 45s
Push Workflows / nix-build (push) Successful in 5m11s
2026-07-14 20:32:46 -04:00
b4da87231d Use SecretString in config where appropriate 2026-07-14 20:32:25 -04:00
a976f04f7d Add SecretString type to config 2026-07-14 20:32:04 -04:00
2 changed files with 52 additions and 15 deletions

View File

@@ -7,6 +7,34 @@ use serde::Deserialize;
/// (Secure cookies can't be set over HTTP. Rough assumption: development is done over HTTP)
const DEFAULT_COOKIES_SECURE: bool = cfg!(not(debug_assertions));
// Simple newtype to avoid showing secrets with `Debug` / `Display`
#[derive(Clone, Deserialize)]
pub struct SecretString(String);
impl SecretString {
pub fn expose(&self) -> &String {
&self.0
}
}
impl From<String> for SecretString {
fn from(s: String) -> Self {
Self(s)
}
}
impl std::fmt::Debug for SecretString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "*****")
}
}
impl std::fmt::Display for SecretString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "*****")
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuthConfig {
pub open_signup: bool,
@@ -16,11 +44,11 @@ pub struct AuthConfig {
/// Build a connection URI from parts
fn format_uri(
scheme: &str,
username: &Option<String>,
password: &Option<String>,
username: Option<&String>,
password: Option<&String>,
host: &str,
port: &Option<u16>,
path: &Option<String>,
port: Option<u16>,
path: Option<&String>,
) -> String {
let mut url = format!("{scheme}://");
@@ -64,14 +92,14 @@ impl DatabaseConfig {
#[serde(untagged)]
enum DatabaseConnectionConfig {
FromUrl {
url: String,
url: SecretString,
},
FromParts {
host: String,
port: Option<u16>,
database: Option<String>,
username: Option<String>,
password: Option<String>,
password: Option<SecretString>,
},
}
@@ -79,14 +107,21 @@ impl DatabaseConnectionConfig {
/// Convert this configuration into the Postgres connection URI
pub fn as_uri(&self) -> String {
match self {
Self::FromUrl { url } => url.clone(),
Self::FromUrl { url } => url.expose().clone(),
Self::FromParts {
host,
port,
database,
username,
password,
} => format_uri("postgres", username, password, host, port, database),
} => format_uri(
"postgres",
username.as_ref(),
password.as_ref().map(|s| s.expose()),
host,
*port,
database.as_ref(),
),
}
}
}
@@ -95,7 +130,7 @@ impl DatabaseConnectionConfig {
#[serde(untagged)]
enum KeyValStoreConnectionConfig {
FromUrl {
url: String,
url: SecretString,
},
FromParts {
scheme: Option<String>,
@@ -103,7 +138,7 @@ enum KeyValStoreConnectionConfig {
port: Option<u16>,
database: Option<String>,
username: Option<String>,
password: Option<String>,
password: Option<SecretString>,
},
}
@@ -111,7 +146,7 @@ impl KeyValStoreConnectionConfig {
/// Convert this configuration into the Redis connection URI
pub fn as_uri(&self) -> String {
match self {
Self::FromUrl { url } => url.clone(),
Self::FromUrl { url } => url.expose().clone(),
Self::FromParts {
scheme,
host,
@@ -121,11 +156,11 @@ impl KeyValStoreConnectionConfig {
password,
} => format_uri(
scheme.as_deref().unwrap_or("redis"),
username,
password,
username.as_ref(),
password.as_ref().map(|s| s.expose().clone()).as_ref(),
host,
port,
database,
*port,
database.as_ref(),
),
}
}

View File

@@ -25,6 +25,8 @@ pub async fn main() -> Result<std::convert::Infallible> {
.map_err(|e| Error::message_here(e.to_string()))
.err_context("Failed to load config")?;
tracing::debug!("Loaded configuration: {config:#?}");
// Dioxus doesn't expose a way to configure the public path other than this environment
// variable, and also doesn't provide a way to read what the public path is. As a workaround we
// expose a config option and set this variable that Dioxus expects.