generated from alecodes/base-template
feat: add basic configuration support
This commit is contained in:
parent
8e1e366964
commit
3ff1f26cc4
6 changed files with 253 additions and 20 deletions
98
src/config.rs
Normal file
98
src/config.rs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
use std::fmt::Display;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::Result;
|
||||
use figment::providers::{Env, Format, Serialized, Toml};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use figment::Figment;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct DBConfig {
|
||||
user: String,
|
||||
password: Option<String>,
|
||||
host: String,
|
||||
name: String,
|
||||
string: Option<String>,
|
||||
}
|
||||
|
||||
impl Display for DBConfig {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.generate_db_string(true))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DBConfig {
|
||||
fn default() -> Self {
|
||||
DBConfig {
|
||||
user: "postgres".to_owned(),
|
||||
password: None,
|
||||
host: "localhost".to_owned(),
|
||||
name: "compendium".to_owned(),
|
||||
string: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DBConfig {
|
||||
pub fn generate_db_string(&self, ofuscate: bool) -> String {
|
||||
if let Some(value) = &self.string {
|
||||
return value.clone();
|
||||
}
|
||||
|
||||
let db_password = if ofuscate {
|
||||
let mut db_password = self.password.clone().unwrap();
|
||||
let password_length = db_password.len();
|
||||
|
||||
let visible_characters = 4;
|
||||
|
||||
if password_length <= visible_characters {
|
||||
// Hide all the password
|
||||
let filler = "*".repeat(password_length);
|
||||
db_password.replace_range(0..password_length, &filler.to_owned());
|
||||
} else {
|
||||
// Hide only a portion of the password
|
||||
let filler = "*".repeat(password_length - visible_characters);
|
||||
db_password.replace_range(visible_characters..password_length, &filler.to_owned());
|
||||
};
|
||||
|
||||
db_password
|
||||
} else {
|
||||
self.password.clone().unwrap()
|
||||
};
|
||||
|
||||
let db_string = format!(
|
||||
"postgres://{}:{}@{}/{}",
|
||||
self.user, db_password, self.host, self.name,
|
||||
);
|
||||
|
||||
db_string.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub db: DBConfig,
|
||||
pub addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Config {
|
||||
db: DBConfig::default(),
|
||||
addr: "0.0.0.0:3000".parse().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(path: PathBuf) -> Result<Self> {
|
||||
let config: Config = Figment::from(Serialized::defaults(Config::default()))
|
||||
.merge(Toml::file(path))
|
||||
.merge(Env::prefixed("CPD_").split("_"))
|
||||
.extract()?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,9 @@ pub enum Error {
|
|||
|
||||
#[error(transparent)]
|
||||
DatabaseOperation(#[from] sqlx::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Config(#[from] figment::Error),
|
||||
}
|
||||
|
||||
impl IntoResponse for Error {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
pub mod config;
|
||||
mod error;
|
||||
pub mod router;
|
||||
|
||||
|
|
|
|||
31
src/main.rs
31
src/main.rs
|
|
@ -2,7 +2,8 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use axum_htmx::AutoVaryLayer;
|
||||
use compendium::{router, AppState, Error, Link, Result, Tx};
|
||||
use compendium::config::Config;
|
||||
use compendium::{config, router, AppState, Error, Link, Result, Tx};
|
||||
use minijinja::{Environment, Value};
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use sqlx::PgPool;
|
||||
|
|
@ -41,25 +42,10 @@ fn load_templates() -> Result<Environment<'static>> {
|
|||
Ok(tmpl_env)
|
||||
}
|
||||
|
||||
async fn init_db() -> Result<PgPool> {
|
||||
let db_string = format!(
|
||||
"postgres://{}:{}@{}/{}",
|
||||
env::var("CPD_DB_USER")?,
|
||||
env::var("CPD_DB_PASSWORD")?,
|
||||
env::var("CPD_DB_HOST")?,
|
||||
env::var("CPD_DB_NAME")?
|
||||
);
|
||||
|
||||
info!("Connecting to database {}", db_string);
|
||||
|
||||
Ok(PgPoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect(&db_string)
|
||||
.await?)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let config = Config::new("./config.toml".into())?;
|
||||
|
||||
// Logs
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
|
|
@ -72,7 +58,12 @@ async fn main() -> Result<()> {
|
|||
|
||||
let mut tmpl_env = load_templates()?;
|
||||
|
||||
let pool = init_db().await?;
|
||||
info!("Connecting to database {}", config.db);
|
||||
|
||||
let pool = PgPoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect(&config.db.generate_db_string(false))
|
||||
.await?;
|
||||
|
||||
let (tx_state, tx_layer) = Tx::setup(pool);
|
||||
|
||||
|
|
@ -86,7 +77,7 @@ async fn main() -> Result<()> {
|
|||
#[cfg(debug_assertions)]
|
||||
let app = app.layer(tower_livereload::LiveReloadLayer::new());
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
|
||||
let listener = tokio::net::TcpListener::bind(config.addr).await?;
|
||||
info!("listening on {}", listener.local_addr()?);
|
||||
|
||||
axum::serve(listener, app).await?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue