use std::{collections::HashSet, net::SocketAddr};
use serde::de::DeserializeOwned;
use crate::{user::Plan, Result};
pub static CONFIG_FILE: &'static str = "micron.toml";
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(default)]
pub struct Config {
pub name: String,
pub version: String,
pub domain: String,
pub address: SocketAddr,
pub assets: Assets,
pub tracing: Tracing,
pub routers: Routers,
pub auth: Auth,
pub oauth: Oauth,
pub registration: Registration,
pub comments: Comments,
pub email: Email,
pub mailing: Mailing,
pub payments: Payments,
pub company: Company,
pub plans: Vec<Plan>,
pub users: Vec<User>,
pub phrases: Vec<String>,
pub dev: DevMode,
pub init: Init,
pub routes: Routes,
}
impl Default for Config {
fn default() -> Self {
Self {
name: env!("CARGO_PKG_NAME").to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
domain: "localhost".to_string(),
address: "127.0.0.1:8080".parse().unwrap(),
assets: Assets::default(),
tracing: Tracing::default(),
routers: Routers::default(),
dev: DevMode::default(),
plans: vec![],
auth: Auth::default(),
oauth: Oauth::default(),
registration: Registration::default(),
users: vec![],
phrases: vec![],
payments: Payments::default(),
company: Company::default(),
email: Email::default(),
mailing: Mailing::default(),
routes: Routes::default(),
comments: Comments::default(),
init: Init::default(),
}
}
}
pub fn load<T: DeserializeOwned>() -> Result<T> {
load_from(CONFIG_FILE)
}
pub fn load_from<T: DeserializeOwned>(name: impl AsRef<str>) -> Result<T> {
let config = config::Config::builder()
.add_source(config::File::with_name(name.as_ref()))
.add_source(config::File::with_name(&format!("secret.{}", name.as_ref())).required(false))
.add_source(
config::Environment::default()
.separator("__")
.prefix_separator("__"),
)
.build()?;
let config: T = config.try_deserialize()?;
Ok(config)
}
pub fn load_from_many<T: DeserializeOwned>(paths: &[impl AsRef<str>]) -> Result<T> {
let mut builder = config::Config::builder().add_source(
config::Environment::default()
.separator("__")
.prefix_separator("__"),
);
for path in paths {
builder = builder.add_source(config::File::with_name(path.as_ref()));
}
let config = builder.build()?;
let config: T = config.try_deserialize()?;
Ok(config)
}
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
#[serde(default)]
pub struct User {
#[serde(flatten)]
pub user: crate::User,
pub avatar: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(default)]
pub struct Assets {
pub serve: bool,
pub path: String,
}
impl Default for Assets {
fn default() -> Self {
Self {
serve: true,
path: "assets".to_string(),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(default)]
pub struct Tracing {
pub enabled: bool,
pub mode: crate::tracing::Mode,
pub level: crate::tracing::Level,
pub loki_address: String,
pub loki_token: String,
}
impl Default for Tracing {
fn default() -> Self {
Self {
enabled: true,
mode: crate::tracing::Mode::default(),
level: crate::tracing::Level::default(),
loki_address: "".to_string(),
loki_token: "".to_string(),
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct Routers {
pub user: bool,
pub auth: bool,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct DevMode {
pub enabled: bool,
pub autologin: Option<String>,
pub mock: bool,
pub mock_regen: bool,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(default)]
pub struct Init {
pub enabled: bool,
}
impl Default for Init {
fn default() -> Self {
Self { enabled: true }
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct Routes {
pub enable: Vec<String>,
pub disable: Vec<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Payments {
pub stripe: Stripe,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Stripe {
pub secret: String,
pub test_secret: String,
pub signing_secret: String,
pub test_signing_secret: String,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct Auth {
pub require_confirmed_email: bool,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct Oauth {
pub enabled: bool,
pub discord: OauthEntry,
pub facebook: OauthEntry,
pub github: OauthEntry,
pub google: OauthEntry,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct OauthEntry {
pub enabled: bool,
pub client_id: String,
pub client_secret: String,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct Registration {
pub enabled: bool,
pub email: bool,
pub email_verification: bool,
pub oauth: bool,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(default)]
pub struct Comments {
pub rate_limit: Option<usize>,
}
impl Default for Comments {
fn default() -> Self {
Self {
rate_limit: Some(30),
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct Email {
pub address: String,
pub smtp_server: String,
pub smtp_port: u16,
pub smtp_user: String,
pub smtp_password: String,
pub confirmation: Option<(String, String, String)>,
pub mailing_confirmation: Option<(String, String, String)>,
pub password_reset: Option<(String, String, String)>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(default)]
pub struct Mailing {
pub lists: HashSet<String>,
pub confirmation: bool,
}
impl Default for Mailing {
fn default() -> Self {
let mut lists = HashSet::new();
lists.insert("main".to_string());
Self {
lists,
confirmation: true,
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct MailingList {
pub name: String,
pub description: String,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct Company {
pub name: String,
pub tax_id: String,
pub country: String,
}