add client config

This commit is contained in:
naskya 2024-06-20 04:46:10 +09:00
parent 2660ff9a70
commit ec03c53208
Signed by: naskya
GPG key ID: 712D413B3A9FED5C
5 changed files with 137 additions and 56 deletions

1
Cargo.lock generated
View file

@ -425,6 +425,7 @@ dependencies = [
"clap", "clap",
"color-print", "color-print",
"serde", "serde",
"serde_json",
"sqlx", "sqlx",
"thiserror", "thiserror",
"tokio", "tokio",

View file

@ -10,6 +10,7 @@ clap = { version = "4.5", features = ["derive"] }
color-print = "0.3" color-print = "0.3"
thiserror = "1.0" thiserror = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] } sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] }
tokio = { version = "1.38", features = ["full"] } tokio = { version = "1.38", features = ["full"] }
toml = "0.8" toml = "0.8"

View file

@ -1,56 +1,2 @@
// This module is only for the schema definition. Always use `Option<T>` for mod client;
// optional values, and do not implement `Default`s or use `#[serde(default)]`s. mod server;
// Optional values are handled in the main Firefish program, and this tool
// does not take care of it.
use serde::{Deserialize, Serialize};
use validator::Validate;
type Port = u16;
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Config {
network: Network,
database: Database,
cache_server: CacheServer,
id: Option<Id>,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Network {
protocol: Option<HttpProtocol>,
host: String,
port: Port,
}
#[derive(Deserialize, Serialize, Debug)]
pub(super) enum HttpProtocol {
Https,
Http,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Database {
host: String,
port: Port,
user: String,
password: String,
name: String,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct CacheServer {
host: String,
port: Port,
user: Option<String>,
password: Option<String>,
index: Option<String>,
prefix: Option<String>,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Id {
#[validate(range(min = 16, max = 24))]
length: Option<u8>,
fingerprint: Option<String>,
}

View file

@ -0,0 +1,75 @@
//! Structure of the client config (`config/client.toml`)
// This module is only for the schema definition. Always use `Option<T>` for
// optional values, and do not implement `Default`s or use `#[serde(default)]`s.
// Optional values are handled in the main Firefish program, and this tool
// does not take care of it.
use serde::{Deserialize, Serialize};
use validator::{Validate, ValidationError};
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Config {
appearance: Appearance,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Appearance {
/// Server-wide default light theme
light_theme: Option<String>,
/// Server-wide default light theme
dark_theme: Option<String>,
#[validate(url)]
icon: Option<String>,
#[validate(url)]
banner_image: Option<String>,
#[validate(url)]
background_image: Option<String>,
#[validate(custom(function = "is_color_code"))]
theme_color: Option<String>,
}
fn is_color_code(color_code: &str) -> Result<(), ValidationError> {
let length = color_code.len();
if length == 0 || !color_code.starts_with('#') {
return Err(ValidationError::new(
"color code must starts with a number sign",
));
}
if length != (1 + 3) && length != (1 + 6) {
return Err(ValidationError::new("color code must be 3 or 6 digits"));
}
if !color_code[1..]
.chars()
.all(|c| c.is_ascii_digit() || ('a'..='f').contains(&c) || ('A'..='F').contains(&c))
{
return Err(ValidationError::new(
"color code must be a hexadecimal number",
));
}
Ok(())
}
#[cfg(test)]
mod unit_test {
#[test]
fn is_color_code() {
super::is_color_code("#fff").unwrap();
super::is_color_code("#FFF").unwrap();
super::is_color_code("#000").unwrap();
super::is_color_code("#a32").unwrap();
super::is_color_code("#101010").unwrap();
super::is_color_code("#1ad010").unwrap();
super::is_color_code("#f9d43c").unwrap();
super::is_color_code("#g9d43c").unwrap_err();
super::is_color_code("#1234").unwrap_err();
super::is_color_code("#1").unwrap_err();
super::is_color_code("#a").unwrap_err();
super::is_color_code("101010").unwrap_err();
super::is_color_code("fff").unwrap_err();
super::is_color_code("##fff").unwrap_err();
super::is_color_code("なつ").unwrap_err();
}
}

View file

@ -0,0 +1,58 @@
//! Structure of the server config (`config/server.toml`)
// This module is only for the schema definition. Always use `Option<T>` for
// optional values, and do not implement `Default`s or use `#[serde(default)]`s.
// Optional values are handled in the main Firefish program, and this tool
// does not take care of it.
use serde::{Deserialize, Serialize};
use validator::Validate;
type Port = u16;
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Config {
network: Network,
database: Database,
cache_server: CacheServer,
id: Option<Id>,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Network {
protocol: Option<HttpProtocol>,
host: String,
port: Port,
}
#[derive(Deserialize, Serialize, Debug)]
pub(super) enum HttpProtocol {
Https,
Http,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Database {
host: String,
port: Port,
user: String,
password: String,
name: String,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct CacheServer {
host: String,
port: Port,
user: Option<String>,
password: Option<String>,
index: Option<String>,
prefix: Option<String>,
}
#[derive(Deserialize, Serialize, Validate, Debug)]
pub(super) struct Id {
#[validate(range(min = 16, max = 24))]
length: Option<u8>,
fingerprint: Option<String>,
}