clean up .env settings

This commit is contained in:
Brent Schroeter 2025-11-18 20:38:01 -08:00
parent aed6ba6495
commit cf46675971
4 changed files with 50 additions and 33 deletions

12
.env.example Normal file
View file

@ -0,0 +1,12 @@
RUST_LOG=debug
ROOT_PATH=/app
FRONTEND_HOST=http://127.0.0.1:8080
DATABASE_URL=postgresql://postgres:guest@127.0.0.1/postgres
HOST=0.0.0.0
SERVER_SECRET=guest
AUTH__CLIENT_ID=
AUTH__CLIENT_SECRET=
AUTH__AUTH_URL=
AUTH__TOKEN_URL=
AUTH__USERINFO_URL=
AUTH__LOGOUT_URL=

View file

@ -16,14 +16,13 @@
use anyhow::Result;
use clap::Parser as _;
use dotenvy::dotenv;
use phono_models::MIGRATOR;
use tracing_subscriber::EnvFilter;
use crate::{
app::App,
cli::{Cli, Commands, serve_command, worker_command},
settings::Settings,
settings::{Settings, load_dotenv},
};
mod app;
@ -48,8 +47,8 @@ mod workspace_utils;
/// Run CLI
#[tokio::main]
async fn main() -> Result<()> {
// Attempt to pre-load .env in case it contains a RUST_LOG variable
dotenv().ok();
load_dotenv()?;
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.init();

View file

@ -5,10 +5,15 @@ use axum::extract::FromRef;
use config::{Config, Environment};
use dotenvy::dotenv;
use serde::Deserialize;
use tracing::info;
use url::Url;
use crate::app::App;
/// Runtime application configuration values, typically read from environment
/// variables.
///
/// This may be used with the [`axum::extract::State`] extractor.
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct Settings {
/// Prefix under which to nest all routes. If specified, include leading
@ -17,11 +22,6 @@ pub(crate) struct Settings {
#[serde(default)]
pub(crate) root_path: String,
/// When set to 1, dev features such as the frontend reloader will be
/// enabled.
#[serde(default)]
pub(crate) dev: u8,
/// postgresql:// URL for Phonograph's application database.
pub(crate) database_url: Url,
@ -58,13 +58,19 @@ fn default_host() -> String {
"127.0.0.1".to_owned()
}
/// OAuth2 and session cookie settings.
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct AuthSettings {
pub(crate) client_id: String,
pub(crate) client_secret: String,
pub(crate) auth_url: String,
pub(crate) token_url: String,
pub(crate) userinfo_url: String,
pub(crate) logout_url: Option<String>,
#[serde(default = "default_cookie_name")]
@ -72,28 +78,12 @@ pub(crate) struct AuthSettings {
}
fn default_cookie_name() -> String {
"ITM_SESSION".to_string()
"PHONO_SESSION".to_string()
}
impl Settings {
/// Load environment variables into a [`Settings`] struct.
pub(crate) fn load() -> Result<Self> {
match dotenv() {
Err(err) => {
if err.not_found() {
tracing::info!("no .env file found");
} else {
return Err(err).context("dotenvy error");
}
}
Ok(pathbuf) => {
tracing::info!(
"using env file {}",
pathbuf
.to_str()
.ok_or(anyhow::anyhow!("pathbuf is not valid unicode"))?
);
}
}
let s = Config::builder()
.add_source(Environment::default().separator("__"))
.build()
@ -107,3 +97,25 @@ impl FromRef<App> for Settings {
state.settings.clone()
}
}
/// Attempt to load environment variables from .env file.
pub(crate) fn load_dotenv() -> Result<()> {
dotenv()
.map(|pathbuf| {
info!(
"using env file {0}",
pathbuf
.to_str()
.ok_or(anyhow::anyhow!("pathbuf is not valid unicode"))?
);
Ok(())
})
.or_else(|err| {
if err.not_found() {
info!("no env file loaded");
Ok(Ok(()))
} else {
Err(err)
}
})?
}

View file

@ -9,11 +9,5 @@
</head>
<body>
{% block main %}{% endblock %}
{% if settings.dev != 0 %}
<script type="module">
import { initDevReloader } from "{{ settings.root_path }}/dev_reloader.mjs";
initDevReloader("{{ settings.frontend_host }}{{ settings.root_path }}/__dev-healthz");
</script>
{% endif %}
</body>
</html>