init
Some checks failed
CI / ci (push) Failing after 1m48s

This commit is contained in:
2026-08-25 23:24:36 +02:00
commit 95739892de
466 changed files with 33918 additions and 0 deletions

8
crates/config/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "config"
edition.workspace = true
version.workspace = true
[dependencies]
thiserror.workspace = true
serde.workspace = true

View File

@@ -0,0 +1,12 @@
use super::{AuthConfig, EntryConfig, PresetConfig, PushConfig, ServerConfig, StorageConfig};
#[derive(Debug, Default, Clone, serde::Deserialize)]
#[serde(default)]
pub struct AppConfig {
pub server: ServerConfig,
pub entry: EntryConfig,
pub storage: StorageConfig,
pub auth: AuthConfig,
pub push: PushConfig,
pub preset: PresetConfig,
}

View File

@@ -0,0 +1,22 @@
const DEFAULT_ACCESS_TOKEN_TTL_SECONDS: u64 = 900;
const DEFAULT_REFRESH_TOKEN_TTL_SECONDS: u64 = 2_592_000;
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(default)]
pub struct AuthConfig {
pub jwt_secret: Option<String>,
pub access_token_ttl_seconds: u64,
pub refresh_token_ttl_seconds: u64,
pub allow_registration: bool,
}
impl Default for AuthConfig {
fn default() -> Self {
Self {
jwt_secret: None,
access_token_ttl_seconds: DEFAULT_ACCESS_TOKEN_TTL_SECONDS,
refresh_token_ttl_seconds: DEFAULT_REFRESH_TOKEN_TTL_SECONDS,
allow_registration: true,
}
}
}

View File

@@ -0,0 +1,24 @@
const DEFAULT_MAX_CONTENT_LENGTH: usize = 65_536;
const DEFAULT_MAX_PHOTOS: usize = 10;
const DEFAULT_MAX_VOICE_MEMOS: usize = 5;
const DEFAULT_MAX_ACTIVITIES_PER_ENTRY: usize = 50;
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(default)]
pub struct EntryConfig {
pub max_content_length: usize,
pub max_photos: usize,
pub max_voice_memos: usize,
pub max_activities_per_entry: usize,
}
impl Default for EntryConfig {
fn default() -> Self {
Self {
max_content_length: DEFAULT_MAX_CONTENT_LENGTH,
max_photos: DEFAULT_MAX_PHOTOS,
max_voice_memos: DEFAULT_MAX_VOICE_MEMOS,
max_activities_per_entry: DEFAULT_MAX_ACTIVITIES_PER_ENTRY,
}
}
}

15
crates/config/src/lib.rs Normal file
View File

@@ -0,0 +1,15 @@
mod app_config;
mod auth_config;
mod entry_config;
mod preset;
mod push_config;
mod server_config;
mod storage_config;
pub use app_config::AppConfig;
pub use auth_config::AuthConfig;
pub use entry_config::EntryConfig;
pub use preset::{PresetActivity, PresetConfig};
pub use push_config::PushConfig;
pub use server_config::{CorsConfig, ServerConfig};
pub use storage_config::{MediaBackend, StorageConfig};

View File

@@ -0,0 +1,48 @@
#[derive(Debug, Clone, serde::Deserialize)]
pub struct PresetActivity {
pub name: String,
pub category: Option<String>,
}
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(default)]
pub struct PresetConfig {
pub activities: Vec<PresetActivity>,
}
impl Default for PresetConfig {
fn default() -> Self {
Self {
activities: default_activities(),
}
}
}
fn default_activities() -> Vec<PresetActivity> {
let groups: &[(&str, &[&str])] = &[
("social", &["family", "friends", "date", "party"]),
(
"hobbies",
&["movies & tv", "reading", "gaming", "sport", "relax"],
),
(
"sleep",
&["sleep early", "good sleep", "medium sleep", "bad sleep"],
),
(
"health",
&["exercise", "eat healthy", "drink water", "walk"],
),
("chores", &["shopping", "cleaning", "cooking", "laundry"]),
];
groups
.iter()
.flat_map(|(category, names)| {
names.iter().map(move |name| PresetActivity {
name: (*name).into(),
category: Some((*category).into()),
})
})
.collect()
}

View File

@@ -0,0 +1,7 @@
#[derive(Debug, Default, Clone, serde::Deserialize)]
#[serde(default)]
pub struct PushConfig {
pub enabled: bool,
pub vapid_private_key: Option<String>,
pub vapid_subject: Option<String>,
}

View File

@@ -0,0 +1,42 @@
const DEFAULT_HOST: &str = "0.0.0.0";
const DEFAULT_PORT: u16 = 3000;
const DEFAULT_MAX_BODY_SIZE: usize = 10 * 1024 * 1024;
const DEFAULT_SPA_DIR: &str = "spa/dist";
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(default)]
pub struct ServerConfig {
pub host: String,
pub port: u16,
pub max_body_size: usize,
pub spa_dir: String,
pub cors: CorsConfig,
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
host: DEFAULT_HOST.into(),
port: DEFAULT_PORT,
max_body_size: DEFAULT_MAX_BODY_SIZE,
spa_dir: DEFAULT_SPA_DIR.into(),
cors: CorsConfig::default(),
}
}
}
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(default)]
pub struct CorsConfig {
pub allowed_origins: Vec<String>,
pub allow_any_origin: bool,
}
impl Default for CorsConfig {
fn default() -> Self {
Self {
allowed_origins: Vec::new(),
allow_any_origin: true,
}
}
}

View File

@@ -0,0 +1,43 @@
const DEFAULT_DATA_DIR: &str = "./data";
const DEFAULT_MEDIA_DIR: &str = "media";
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(tag = "backend")]
pub enum MediaBackend {
#[serde(rename = "local")]
Local { media_dir: String },
#[serde(rename = "s3")]
S3 {
bucket: String,
region: String,
endpoint: Option<String>,
access_key: Option<String>,
secret_key: Option<String>,
},
}
impl Default for MediaBackend {
fn default() -> Self {
Self::Local {
media_dir: DEFAULT_MEDIA_DIR.into(),
}
}
}
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(default)]
pub struct StorageConfig {
pub data_dir: String,
pub database_url: Option<String>,
pub media: MediaBackend,
}
impl Default for StorageConfig {
fn default() -> Self {
Self {
data_dir: DEFAULT_DATA_DIR.into(),
database_url: None,
media: MediaBackend::default(),
}
}
}