Le dépôt des textes créé par Yvv sur git.open.us.org (2026-10-21) : séparé du code, pour que la clé du serveur n'écrive jamais dans yvv/decision et que le dépôt se transfère d'un bloc à l'ouverture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
140 lines
5.0 KiB
Rust
140 lines
5.0 KiB
Rust
//! Configuration, from the environment only. Secrets never have a default.
|
|
|
|
use std::path::PathBuf;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Connect {
|
|
/// Base URL of the sso-connect instance (no trailing slash).
|
|
pub base_url: String,
|
|
pub client_id: String,
|
|
pub client_secret: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Publish {
|
|
/// Remote of the texts repository, e.g. `gitea@git.open.us.org:yvv/decision-depot-textes-reference.git`.
|
|
pub remote: String,
|
|
pub branch: String,
|
|
/// Private SSH key allowed to push there (deploy key).
|
|
pub key: PathBuf,
|
|
pub author_name: String,
|
|
pub author_email: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Config {
|
|
pub bind: String,
|
|
pub data_dir: PathBuf,
|
|
pub web_dir: PathBuf,
|
|
pub seed_dir: PathBuf,
|
|
/// Public origin, e.g. `https://decision.librodrome.org` — callbacks and cookies.
|
|
pub public_url: String,
|
|
pub connect: Option<Connect>,
|
|
pub admin_g1_ids: Vec<String>,
|
|
pub dev_login: bool,
|
|
pub bootstrap_admin: bool,
|
|
pub publish: Option<Publish>,
|
|
pub rpc_endpoints: Vec<String>,
|
|
pub indexers: Vec<String>,
|
|
pub wot_fallback: u32,
|
|
pub build: String,
|
|
}
|
|
|
|
fn var(name: &str) -> Option<String> {
|
|
std::env::var(name).ok().map(|v| v.trim().to_owned()).filter(|v| !v.is_empty())
|
|
}
|
|
|
|
fn flag(name: &str) -> bool {
|
|
var(name).is_some_and(|v| matches!(v.as_str(), "1" | "true" | "yes" | "on"))
|
|
}
|
|
|
|
fn list(name: &str, default: &[&str]) -> Vec<String> {
|
|
match var(name) {
|
|
Some(v) => v.split(',').map(|s| s.trim().to_owned()).filter(|s| !s.is_empty()).collect(),
|
|
None => default.iter().map(|s| (*s).to_owned()).collect(),
|
|
}
|
|
}
|
|
|
|
impl Config {
|
|
pub fn from_env() -> Self {
|
|
let data_dir = PathBuf::from(var("LD_DATA_DIR").unwrap_or_else(|| "data".into()));
|
|
let connect = match (var("LD_CONNECT_CLIENT_ID"), var("LD_CONNECT_CLIENT_SECRET")) {
|
|
(Some(client_id), Some(client_secret)) => Some(Connect {
|
|
base_url: var("LD_CONNECT_URL")
|
|
.unwrap_or_else(|| "https://connect.monnaie-libre.fr".into())
|
|
.trim_end_matches('/')
|
|
.to_owned(),
|
|
client_id,
|
|
client_secret,
|
|
}),
|
|
_ => None,
|
|
};
|
|
let publish = var("LD_PUBLISH_REMOTE").map(|remote| Publish {
|
|
remote,
|
|
branch: var("LD_PUBLISH_BRANCH").unwrap_or_else(|| "main".into()),
|
|
key: var("LD_PUBLISH_KEY").map(PathBuf::from).unwrap_or_else(|| data_dir.join("keys/publish_ed25519")),
|
|
author_name: var("LD_PUBLISH_AUTHOR").unwrap_or_else(|| "libreDecision".into()),
|
|
author_email: var("LD_PUBLISH_EMAIL").unwrap_or_else(|| "decision@librodrome.org".into()),
|
|
});
|
|
Self {
|
|
bind: var("LD_BIND").unwrap_or_else(|| "0.0.0.0:8002".into()),
|
|
web_dir: PathBuf::from(var("LD_WEB_DIR").unwrap_or_else(|| "web/build".into())),
|
|
seed_dir: PathBuf::from(var("LD_SEED_DIR").unwrap_or_else(|| "seeds".into())),
|
|
public_url: var("LD_PUBLIC_URL")
|
|
.unwrap_or_else(|| "http://127.0.0.1:3002".into())
|
|
.trim_end_matches('/')
|
|
.to_owned(),
|
|
connect,
|
|
admin_g1_ids: list("LD_ADMIN_G1_IDS", &[]),
|
|
dev_login: flag("LD_DEV_LOGIN"),
|
|
bootstrap_admin: flag("LD_BOOTSTRAP_ADMIN"),
|
|
publish,
|
|
rpc_endpoints: list(
|
|
"LD_RPC_ENDPOINTS",
|
|
&[
|
|
"https://rpc.duniter.org",
|
|
"https://g1.axiom-team.fr/ws/",
|
|
"https://g1.asycn.io/ws/",
|
|
"https://g1.coinduf.eu",
|
|
],
|
|
),
|
|
indexers: list(
|
|
"LD_INDEXERS",
|
|
&["https://indexer.duniter.org/v1/graphql", "https://g1-squid.axiom-team.fr/v1/graphql"],
|
|
),
|
|
wot_fallback: var("LD_WOT_FALLBACK").and_then(|v| v.parse().ok()).unwrap_or(5745),
|
|
build: var("LD_BUILD").unwrap_or_else(|| "dev".into()),
|
|
data_dir,
|
|
}
|
|
}
|
|
|
|
/// Cookies are `Secure` as soon as the public origin is https.
|
|
pub fn secure_cookies(&self) -> bool {
|
|
self.public_url.starts_with("https://")
|
|
}
|
|
|
|
pub fn connect_callback(&self) -> String {
|
|
format!("{}/api/auth/g1/callback", self.public_url)
|
|
}
|
|
|
|
/// For tests: an in-memory configuration with dev login.
|
|
pub fn for_tests() -> Self {
|
|
Self {
|
|
bind: "127.0.0.1:0".into(),
|
|
data_dir: std::env::temp_dir().join("ld-tests"),
|
|
web_dir: PathBuf::from("web/build"),
|
|
seed_dir: PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/../../seeds")),
|
|
public_url: "http://127.0.0.1:3002".into(),
|
|
connect: None,
|
|
admin_g1_ids: vec!["idty:8352".into()],
|
|
dev_login: true,
|
|
bootstrap_admin: false,
|
|
publish: None,
|
|
rpc_endpoints: vec![],
|
|
indexers: vec![],
|
|
wot_fallback: 5745,
|
|
build: "test".into(),
|
|
}
|
|
}
|
|
}
|