Add QR codes, link expiry, password protection, previews, audit trail and bulk operations

This commit is contained in:
thakares committed 2026-06-12 19:57:53 +05:30
1 parent 157aa81252
commit bcbcc90d98
88 files changed
+5354 -815

No files matched your search

+86 -27
View File
@@ -1,7 +1,7 @@
use std::path::PathBuf;
use serde::Deserialize;
use std::env;
use std::fs;
use serde::Deserialize;
use std::path::PathBuf;
#[derive(Clone, Debug)]
pub struct Config {
@@ -18,6 +18,7 @@ pub struct Config {
pub backup_enabled: bool,
pub backup_interval_mins: u64,
pub backup_dir: PathBuf,
pub base_url: Option<String>,
}
#[derive(Deserialize, Default)]
@@ -33,6 +34,7 @@ struct TomlConfig {
link_check_interval_mins: Option<u64>,
aggregation_interval_mins: Option<u64>,
backup: Option<TomlBackupConfig>,
base_url: Option<String>,
}
#[derive(Deserialize, Default)]
@@ -50,7 +52,8 @@ impl Config {
let mut data_dir = PathBuf::from("./data");
let mut admin_username = "admin".to_string();
let mut bootstrap_password_sha256 = "".to_string();
let mut session_secret = "bzod-default-session-secret-change-me-in-production-please-do-it".to_string();
let mut session_secret =
"bzod-default-session-secret-change-me-in-production-please-do-it".to_string();
let mut cookie_secure = true;
let mut data_retention_days = None;
let mut link_check_interval_mins = 60u64;
@@ -58,6 +61,7 @@ impl Config {
let mut backup_enabled = false;
let mut backup_interval_mins = 1440u64; // Default: once per day
let mut backup_dir = PathBuf::from("./backups");
let mut base_url = None;
// 2. Load bzod.toml if it exists
let mut toml_path = "bzod.toml".to_string();
@@ -66,13 +70,27 @@ impl Config {
}
if let Ok(toml_content) = fs::read_to_string(&toml_path) {
if let Ok(toml_config) = toml::from_str::<TomlConfig>(&toml_content) {
if let Some(h) = toml_config.host { host = h; }
if let Some(p) = toml_config.port { port = p; }
if let Some(d) = toml_config.data_dir { data_dir = PathBuf::from(d); }
if let Some(u) = toml_config.admin_username { admin_username = u; }
if let Some(s) = toml_config.bootstrap_password_sha256 { bootstrap_password_sha256 = s; }
if let Some(sec) = toml_config.session_secret { session_secret = sec; }
if let Some(c) = toml_config.cookie_secure { cookie_secure = c; }
if let Some(h) = toml_config.host {
host = h;
}
if let Some(p) = toml_config.port {
port = p;
}
if let Some(d) = toml_config.data_dir {
data_dir = PathBuf::from(d);
}
if let Some(u) = toml_config.admin_username {
admin_username = u;
}
if let Some(s) = toml_config.bootstrap_password_sha256 {
bootstrap_password_sha256 = s;
}
if let Some(sec) = toml_config.session_secret {
session_secret = sec;
}
if let Some(c) = toml_config.cookie_secure {
cookie_secure = c;
}
if let Some(ret) = toml_config.data_retention_days {
if ret.eq_ignore_ascii_case("unlimited") {
data_retention_days = None;
@@ -80,12 +98,25 @@ impl Config {
data_retention_days = Some(parsed);
}
}
if let Some(lc) = toml_config.link_check_interval_mins { link_check_interval_mins = lc; }
if let Some(ag) = toml_config.aggregation_interval_mins { aggregation_interval_mins = ag; }
if let Some(lc) = toml_config.link_check_interval_mins {
link_check_interval_mins = lc;
}
if let Some(ag) = toml_config.aggregation_interval_mins {
aggregation_interval_mins = ag;
}
if let Some(b) = toml_config.backup {
if let Some(be) = b.enabled { backup_enabled = be; }
if let Some(bi) = b.interval_mins { backup_interval_mins = bi; }
if let Some(bo) = b.out_dir { backup_dir = PathBuf::from(bo); }
if let Some(be) = b.enabled {
backup_enabled = be;
}
if let Some(bi) = b.interval_mins {
backup_interval_mins = bi;
}
if let Some(bo) = b.out_dir {
backup_dir = PathBuf::from(bo);
}
}
if let Some(bu) = toml_config.base_url {
base_url = Some(bu);
}
}
}
@@ -97,16 +128,30 @@ impl Config {
}
// 4. Load from Environment Variables (taking highest precedence)
if let Ok(h) = env::var("HOST") { host = h; }
if let Ok(h) = env::var("HOST") {
host = h;
}
if let Ok(p_str) = env::var("PORT") {
if let Ok(p) = p_str.parse::<u16>() { port = p; }
if let Ok(p) = p_str.parse::<u16>() {
port = p;
}
}
if let Ok(d_str) = env::var("DATA_DIR") {
data_dir = PathBuf::from(d_str);
}
if let Ok(u) = env::var("ADMIN_USERNAME") {
admin_username = u;
}
if let Ok(s) = env::var("BOOTSTRAP_PASSWORD_SHA256") {
bootstrap_password_sha256 = s;
}
if let Ok(sec) = env::var("SESSION_SECRET") {
session_secret = sec;
}
if let Ok(d_str) = env::var("DATA_DIR") { data_dir = PathBuf::from(d_str); }
if let Ok(u) = env::var("ADMIN_USERNAME") { admin_username = u; }
if let Ok(s) = env::var("BOOTSTRAP_PASSWORD_SHA256") { bootstrap_password_sha256 = s; }
if let Ok(sec) = env::var("SESSION_SECRET") { session_secret = sec; }
if let Ok(c_str) = env::var("COOKIE_SECURE") {
if let Ok(c) = c_str.parse::<bool>() { cookie_secure = c; }
if let Ok(c) = c_str.parse::<bool>() {
cookie_secure = c;
}
}
if let Ok(ret_str) = env::var("DATA_RETENTION_DAYS") {
if ret_str.eq_ignore_ascii_case("unlimited") {
@@ -116,18 +161,31 @@ impl Config {
}
}
if let Ok(lc_str) = env::var("LINK_CHECK_INTERVAL_MINS") {
if let Ok(lc) = lc_str.parse::<u64>() { link_check_interval_mins = lc; }
if let Ok(lc) = lc_str.parse::<u64>() {
link_check_interval_mins = lc;
}
}
if let Ok(ag_str) = env::var("AGGREGATION_INTERVAL_MINS") {
if let Ok(ag) = ag_str.parse::<u64>() { aggregation_interval_mins = ag; }
if let Ok(ag) = ag_str.parse::<u64>() {
aggregation_interval_mins = ag;
}
}
if let Ok(be_str) = env::var("BACKUP_ENABLED") {
if let Ok(be) = be_str.parse::<bool>() { backup_enabled = be; }
if let Ok(be) = be_str.parse::<bool>() {
backup_enabled = be;
}
}
if let Ok(bi_str) = env::var("BACKUP_INTERVAL_MINS") {
if let Ok(bi) = bi_str.parse::<u64>() { backup_interval_mins = bi; }
if let Ok(bi) = bi_str.parse::<u64>() {
backup_interval_mins = bi;
}
}
if let Ok(bo_str) = env::var("BACKUP_DIR") {
backup_dir = PathBuf::from(bo_str);
}
if let Ok(bu) = env::var("BASE_URL") {
base_url = Some(bu);
}
if let Ok(bo_str) = env::var("BACKUP_DIR") { backup_dir = PathBuf::from(bo_str); }
Self {
host,
@@ -143,6 +201,7 @@ impl Config {
backup_enabled,
backup_interval_mins,
backup_dir,
base_url,
}
}
}