rainbeam/config.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
//! Application config manager
use serde::{Deserialize, Serialize};
use std::io::Result;
use authbeam::database::HCaptchaConfig;
use rainbeam_shared::fs;
/// Premium features
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Tiers {
/// Doubled character limits for everything
///
/// * Questions: ~~2048~~ **4096**
/// * Responses: ~~4096~~ **8192**
/// * Comments: ~~2048~~ **4096**
///
/// *\*Carpgraph drawings stay at 32kb maximum*
#[serde(default)]
pub double_limits: i32,
/// Styled profile card in the followers/following/friends section of other users
#[serde(default)]
pub stylish_card: i32,
/// A small little crown shown on the user's profile avatar
#[serde(default)]
pub avatar_crown: i32,
/// A small badge shwon on the user's profile
#[serde(default)]
pub profile_badge: i32,
}
impl Default for Tiers {
/// Everything is tier 1 by default
fn default() -> Self {
Self {
double_limits: 1,
stylish_card: 1,
avatar_crown: 1,
profile_badge: 1,
}
}
}
/// Configuration file
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Config {
/// The port to serve the server on
pub port: u16,
/// The name of the site
pub name: String,
/// The description of the site
pub description: String,
/// The location of the static directory, should not be supplied manually as it will be overwritten with `./.config/static`
#[serde(default)]
pub static_dir: String,
/// HCaptcha configuration
pub captcha: HCaptchaConfig,
/// The name of the header used for reading user IP address
pub real_ip_header: Option<String>,
/// If new profile registration is enabled
#[serde(default)]
pub registration_enabled: bool,
/// The origin of the public server (ex: "https://rainbeam.net")
///
/// Used in embeds and links.
#[serde(default)]
pub host: String,
/// The hostname of the public server (for Citrus)
///
/// Same as `host`, just without the protocol.
#[serde(default)]
pub citrus_id: String,
/// A list of image hosts that are blocked
#[serde(default)]
pub blocked_hosts: Vec<String>,
/// If a migration should be run
#[serde(default)]
pub migration: bool,
/// Tiered benefits
#[serde(default)]
pub tiers: Tiers,
/// A global site announcement shown at the top of the page
#[serde(default)]
pub alert: String,
/// If Citrus should use https or http
#[serde(default = "authbeam::database::secure_default")]
pub secure: bool,
}
impl Default for Config {
fn default() -> Self {
Self {
port: 8080,
name: "Rainbeam".to_string(),
description: "Ask, share, socialize!".to_string(),
static_dir: String::new(),
captcha: HCaptchaConfig::default(),
real_ip_header: Option::None,
registration_enabled: true,
host: String::new(),
citrus_id: String::new(),
blocked_hosts: Vec::new(),
migration: false,
tiers: Tiers::default(),
alert: String::new(),
secure: true,
}
}
}
impl Config {
/// Read configuration file into [`Config`]
pub fn read(contents: String) -> Self {
toml::from_str::<Self>(&contents).unwrap()
}
/// Pull configuration file
pub fn get_config() -> Self {
let c = fs::canonicalize(".").unwrap();
let here = c.to_str().unwrap();
match fs::read(format!("{here}/.config/config.toml")) {
Ok(c) => Config::read(c),
Err(_) => {
Self::update_config(Self::default()).expect("failed to write default config");
Self::default()
}
}
}
/// Update configuration file
pub fn update_config(contents: Self) -> Result<()> {
let c = fs::canonicalize(".").unwrap();
let here = c.to_str().unwrap();
fs::write(
format!("{here}/.config/config.toml"),
toml::to_string_pretty::<Self>(&contents).unwrap(),
)
}
}