1use oiseau::config::{Configuration, DatabaseConfig};
2use pathbufd::PathBufD;
3use serde::{Deserialize, Serialize};
4use std::fs;
5use std::io::Result;
6
7#[derive(Clone, Serialize, Deserialize, Debug)]
9pub struct SecurityConfig {
10 #[serde(default = "default_security_registration_enabled")]
12 pub registration_enabled: bool,
13 #[serde(default = "default_real_ip_header")]
15 pub real_ip_header: String,
16 #[serde(default = "default_enable_invite_codes")]
18 pub enable_invite_codes: bool,
19}
20
21fn default_security_registration_enabled() -> bool {
22 true
23}
24
25fn default_real_ip_header() -> String {
26 "CF-Connecting-IP".to_string()
27}
28
29fn default_enable_invite_codes() -> bool {
30 false
31}
32
33impl Default for SecurityConfig {
34 fn default() -> Self {
35 Self {
36 registration_enabled: default_security_registration_enabled(),
37 real_ip_header: default_real_ip_header(),
38 enable_invite_codes: default_enable_invite_codes(),
39 }
40 }
41}
42
43#[derive(Clone, Serialize, Deserialize, Debug)]
45pub struct DirsConfig {
46 #[serde(default = "default_dir_templates")]
48 pub templates: String,
49 #[serde(default = "default_dir_assets")]
51 pub assets: String,
52 #[serde(default = "default_dir_media")]
54 pub media: String,
55 #[serde(default = "default_dir_icons")]
57 pub icons: String,
58 #[serde(default = "default_dir_docs")]
60 pub docs: String,
61 #[serde(default = "default_dir_rustdoc")]
64 pub rustdoc: String,
65}
66
67fn default_dir_templates() -> String {
68 "html".to_string()
69}
70
71fn default_dir_assets() -> String {
72 "public".to_string()
73}
74
75fn default_dir_media() -> String {
76 "media".to_string()
77}
78
79fn default_dir_icons() -> String {
80 "icons".to_string()
81}
82
83fn default_dir_docs() -> String {
84 "docs".to_string()
85}
86
87fn default_dir_rustdoc() -> String {
88 "reference".to_string()
89}
90
91impl Default for DirsConfig {
92 fn default() -> Self {
93 Self {
94 templates: default_dir_templates(),
95 assets: default_dir_assets(),
96 media: default_dir_media(),
97 icons: default_dir_icons(),
98 docs: default_dir_docs(),
99 rustdoc: default_dir_rustdoc(),
100 }
101 }
102}
103
104impl Configuration for Config {
105 fn db_config(&self) -> DatabaseConfig {
106 self.database.to_owned()
107 }
108}
109
110#[derive(Clone, Serialize, Deserialize, Debug)]
112pub struct PoliciesConfig {
113 pub terms_of_service: String,
119 pub privacy: String,
124 #[serde(default)]
132 pub last_updated: usize,
133}
134
135impl Default for PoliciesConfig {
136 fn default() -> Self {
137 Self {
138 terms_of_service: "/public/tos.html".to_string(),
139 privacy: "/public/privacy.html".to_string(),
140 last_updated: 0,
141 }
142 }
143}
144
145#[derive(Clone, Serialize, Deserialize, Debug)]
147pub struct TurnstileConfig {
148 pub site_key: String,
149 pub secret_key: String,
150}
151
152impl Default for TurnstileConfig {
153 fn default() -> Self {
154 Self {
155 site_key: "1x00000000000000000000AA".to_string(), secret_key: "1x0000000000000000000000000000000AA".to_string(), }
158 }
159}
160
161#[derive(Clone, Serialize, Deserialize, Debug, Default)]
162pub struct ConnectionsConfig {
163 #[serde(default)]
165 pub spotify_client_id: Option<String>,
166 #[serde(default)]
168 pub last_fm_key: Option<String>,
169 #[serde(default)]
171 pub last_fm_secret: Option<String>,
172}
173
174#[derive(Clone, Serialize, Deserialize, Debug, Default)]
185pub struct StripeConfig {
186 pub secret: String,
188 pub payment_links: StripePaymentLinks,
195 pub webhook_signing_secret: String,
203 pub billing_portal_url: String,
207 pub price_texts: StripePriceTexts,
209 pub product_ids: StripeProductIds,
213 pub price_ids: StripePriceIds,
215}
216
217#[derive(Clone, Serialize, Deserialize, Debug, Default)]
218pub struct StripePriceTexts {
219 pub supporter: String,
220 pub dev_pass: String,
221 pub coins_100: String,
222 pub coins_400: String,
223}
224
225#[derive(Clone, Serialize, Deserialize, Debug, Default)]
226pub struct StripePaymentLinks {
227 pub supporter: String,
228 pub dev_pass: String,
229}
230
231#[derive(Clone, Serialize, Deserialize, Debug, Default)]
232pub struct StripeProductIds {
233 pub supporter: String,
234 pub dev_pass: String,
235 pub coins_100: String,
236 pub coins_400: String,
237}
238
239#[derive(Clone, Serialize, Deserialize, Debug, Default)]
240pub struct StripePriceIds {
241 pub coins_100: String,
242 pub coins_400: String,
243}
244
245#[derive(Clone, Serialize, Deserialize, Debug)]
247pub struct ManualsConfig {
248 pub search_help: String,
250}
251
252impl Default for ManualsConfig {
253 fn default() -> Self {
254 Self {
255 search_help: "".to_string(),
256 }
257 }
258}
259
260#[derive(Clone, Serialize, Deserialize, Debug, Default)]
261pub struct ServiceHostsConfig {
262 pub buckets: String,
264 #[serde(default)]
266 pub tawny: String,
267 #[serde(default)]
269 pub shrimpcamp_autter: String,
270}
271
272#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
273pub enum StringBan {
274 String(String),
276 Unicode(u32),
278}
279
280impl Default for StringBan {
281 fn default() -> Self {
282 Self::String(String::new())
283 }
284}
285
286#[derive(Clone, Serialize, Deserialize, Debug)]
288pub struct Config {
289 #[serde(default = "default_name")]
291 pub name: String,
292 #[serde(default = "default_description")]
294 pub description: String,
295 #[serde(default = "default_color")]
297 pub color: String,
298 #[serde(default = "default_port")]
300 pub port: u16,
301 #[serde(default = "default_banned_hosts")]
308 pub banned_hosts: Vec<String>,
309 #[serde(default = "default_host")]
312 pub host: String,
313 #[serde(default = "default_service_hosts")]
315 pub service_hosts: ServiceHostsConfig,
316 #[serde(default = "default_security")]
318 pub security: SecurityConfig,
319 #[serde(default = "default_dirs")]
321 pub dirs: DirsConfig,
322 #[serde(default = "default_database")]
324 pub database: DatabaseConfig,
325 #[serde(default = "default_no_track")]
328 pub no_track: Vec<String>,
329 #[serde(default = "default_banned_usernames")]
331 pub banned_usernames: Vec<String>,
332 #[serde(default = "default_policies")]
334 pub policies: PoliciesConfig,
335 #[serde(default = "default_turnstile")]
337 pub turnstile: TurnstileConfig,
338 #[serde(default)]
343 pub town_square: usize,
344 #[serde(default)]
346 pub town_square_forum: usize,
347 #[serde(default)]
350 pub town_square_forum_topic: usize,
351 #[serde(default)]
353 pub system_user: usize,
354 #[serde(default)]
355 pub connections: ConnectionsConfig,
356 #[serde(default)]
359 pub html_footer_path: String,
360 #[serde(default)]
361 pub stripe: Option<StripeConfig>,
362 #[serde(default)]
364 pub manuals: ManualsConfig,
365 #[serde(default)]
367 pub banned_data: Vec<StringBan>,
368 #[serde(default)]
370 pub enable_user_ads: bool,
371}
372
373fn default_name() -> String {
374 "Tetratto".to_string()
375}
376
377fn default_description() -> String {
378 "🐇 tetratto!".to_string()
379}
380
381fn default_color() -> String {
382 "#c9b1bc".to_string()
383}
384fn default_port() -> u16 {
385 4118
386}
387
388fn default_banned_hosts() -> Vec<String> {
389 Vec::new()
390}
391
392fn default_host() -> String {
393 String::new()
394}
395
396fn default_service_hosts() -> ServiceHostsConfig {
397 ServiceHostsConfig::default()
398}
399
400fn default_security() -> SecurityConfig {
401 SecurityConfig::default()
402}
403
404fn default_dirs() -> DirsConfig {
405 DirsConfig::default()
406}
407
408fn default_database() -> DatabaseConfig {
409 DatabaseConfig::default()
410}
411
412fn default_no_track() -> Vec<String> {
413 Vec::new()
414}
415
416fn default_banned_usernames() -> Vec<String> {
417 vec![
418 "admin".to_string(),
419 "owner".to_string(),
420 "moderator".to_string(),
421 "api".to_string(),
422 "communities".to_string(),
423 "community".to_string(),
424 "notifs".to_string(),
425 "notification".to_string(),
426 "post".to_string(),
427 "void".to_string(),
428 "anonymous".to_string(),
429 "stacks".to_string(),
430 "stack".to_string(),
431 "search".to_string(),
432 "links".to_string(),
433 "app".to_string(),
434 "services".to_string(),
435 "domains".to_string(),
436 "mail".to_string(),
437 "product".to_string(),
438 "wallet".to_string(),
439 "products".to_string(),
440 "market".to_string(),
441 ]
442}
443
444fn default_policies() -> PoliciesConfig {
445 PoliciesConfig::default()
446}
447
448fn default_turnstile() -> TurnstileConfig {
449 TurnstileConfig::default()
450}
451
452fn default_connections() -> ConnectionsConfig {
453 ConnectionsConfig::default()
454}
455
456fn default_manuals() -> ManualsConfig {
457 ManualsConfig::default()
458}
459
460fn default_banned_data() -> Vec<StringBan> {
461 Vec::new()
462}
463
464impl Default for Config {
465 fn default() -> Self {
466 Self {
467 name: default_name(),
468 description: default_description(),
469 color: default_color(),
470 port: default_port(),
471 banned_hosts: default_banned_hosts(),
472 host: default_host(),
473 service_hosts: default_service_hosts(),
474 database: default_database(),
475 security: default_security(),
476 dirs: default_dirs(),
477 no_track: default_no_track(),
478 banned_usernames: default_banned_usernames(),
479 policies: default_policies(),
480 turnstile: default_turnstile(),
481 town_square: 0,
482 town_square_forum: 0,
483 town_square_forum_topic: 0,
484 system_user: 0,
485 connections: default_connections(),
486 html_footer_path: String::new(),
487 stripe: None,
488 manuals: default_manuals(),
489 banned_data: default_banned_data(),
490 enable_user_ads: false,
491 }
492 }
493}
494
495impl Config {
496 pub fn read(contents: String) -> Self {
498 toml::from_str::<Self>(&contents).unwrap()
499 }
500
501 pub fn get_config() -> Self {
503 let path = PathBufD::current().join("app.toml");
504
505 match fs::read_to_string(&path) {
506 Ok(c) => Config::read(c),
507 Err(_) => {
508 Self::update_config(Self::default()).expect("failed to write default config");
509 Self::default()
510 }
511 }
512 }
513
514 pub fn update_config(contents: Self) -> Result<()> {
516 let c = fs::canonicalize(".").unwrap();
517 let here = c.to_str().unwrap();
518
519 fs::write(
520 format!("{here}/app.toml"),
521 toml::to_string_pretty::<Self>(&contents).unwrap(),
522 )
523 }
524}