1use oiseau::config::{Configuration, DatabaseConfig};
2use pathbufd::PathBufD;
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, Serialize, Deserialize)]
6pub struct Config {
7 #[serde(default = "default_name")]
9 pub name: String,
10 #[serde(default = "default_database")]
12 pub database: DatabaseConfig,
13 #[serde(default)]
15 pub service_hosts: ServiceHostsConfig,
16 #[serde(default)]
18 pub host: String,
19 #[serde(default = "default_banned_usernames")]
21 pub banned_usernames: Vec<String>,
22 #[serde(default)]
24 pub security: SecurityConfig,
25 #[serde(default)]
27 pub dirs: DirectoriesConfig,
28 pub stripe: StripeConfig,
30 #[serde(default)]
31 pub turnstile: TurnstileConfig,
32}
33
34fn default_banned_usernames() -> Vec<String> {
35 vec!["admin".to_string(), "settings".to_string()]
36}
37
38#[derive(Clone, Serialize, Deserialize, Debug)]
39pub struct TurnstileConfig {
40 pub site_key: String,
41 pub secret_key: String,
42}
43
44impl Default for TurnstileConfig {
45 fn default() -> Self {
46 Self {
47 site_key: "1x00000000000000000000AA".to_string(), secret_key: "1x0000000000000000000000000000000AA".to_string(), }
50 }
51}
52
53#[derive(Clone, Debug, Serialize, Deserialize, Default)]
54pub struct SecurityConfig {
55 #[serde(default)]
56 pub accepting_purchases: bool,
57 #[serde(default)]
58 pub registration_enabled: bool,
59 #[serde(default = "default_real_ip_header")]
61 pub real_ip_header: String,
62 #[serde(default)]
64 pub approved_login_redirects: Vec<String>,
65}
66
67#[derive(Clone, Debug, Serialize, Deserialize)]
68pub struct ServiceHostsConfig {
69 #[serde(default = "default_shrimpcamp")]
70 pub shrimpcamp: String,
71 #[serde(default = "default_tetratto")]
72 pub tetratto: String,
73 #[serde(default = "default_buckets")]
74 pub buckets: String,
75 #[serde(default = "default_askall")]
76 pub askall: String,
77 #[serde(default = "default_issuestack")]
78 pub issuestack: String,
79 #[serde(default = "default_fluffle")]
80 pub fluffle: String,
81 #[serde(default = "default_overkit")]
82 pub overkit: String,
83 #[serde(default = "default_juicespace")]
84 pub juicespace: String,
85}
86
87fn default_shrimpcamp() -> String {
88 "https://about.shrimpcamp.com".to_string()
89}
90
91fn default_tetratto() -> String {
92 "https://tetratto.com".to_string()
93}
94
95fn default_askall() -> String {
96 "https://askall.cc".to_string()
97}
98
99fn default_issuestack() -> String {
100 "https://stack.shrimpcamp.com".to_string()
101}
102
103fn default_fluffle() -> String {
104 "https://fluffle.cc".to_string()
105}
106
107fn default_buckets() -> String {
108 "http://localhost:8020".to_string()
109}
110
111fn default_overkit() -> String {
112 "http://localhost:8026".to_string()
113}
114
115fn default_juicespace() -> String {
116 "https://juicespace.org".to_string()
117}
118
119impl Default for ServiceHostsConfig {
120 fn default() -> Self {
121 Self {
122 shrimpcamp: default_shrimpcamp(),
123 tetratto: default_tetratto(),
124 buckets: default_buckets(),
125 askall: default_askall(),
126 issuestack: default_issuestack(),
127 fluffle: default_fluffle(),
128 overkit: default_overkit(),
129 juicespace: default_juicespace(),
130 }
131 }
132}
133
134#[derive(Clone, Debug, Serialize, Deserialize)]
135pub struct DirectoriesConfig {
136 #[serde(default = "default_media")]
137 pub media: String,
138}
139
140fn default_media() -> String {
141 "media".to_string()
142}
143
144impl Default for DirectoriesConfig {
145 fn default() -> Self {
146 Self {
147 media: default_media(),
148 }
149 }
150}
151
152fn default_name() -> String {
153 "Autter".to_string()
154}
155
156fn default_real_ip_header() -> String {
157 "CF-Connecting-IP".to_string()
158}
159
160fn default_database() -> DatabaseConfig {
161 DatabaseConfig::default()
162}
163
164#[derive(Clone, Serialize, Deserialize, Debug, Default)]
175pub struct StripeConfig {
176 pub secret: String,
178 pub webhook_signing_secret: String,
186 pub billing_portal_url: String,
190 pub price_texts: StripePriceTexts,
192 pub product_ids: StripeProductIds,
196 pub price_ids: StripePriceIds,
198}
199
200#[derive(Clone, Serialize, Deserialize, Debug, Default)]
201pub struct StripePriceTexts {
202 pub organization: String,
203 pub user_reg: String,
204 pub seedling: String,
205 pub user_verification: String,
206}
207
208#[derive(Clone, Serialize, Deserialize, Debug, Default)]
209pub struct StripeProductIds {
210 pub organization: String,
211 pub user_reg: String,
212 pub seedling: String,
213 pub user_verification: String,
214}
215
216#[derive(Clone, Serialize, Deserialize, Debug, Default)]
217pub struct StripePriceIds {
218 pub organization: String,
219 pub user_reg: String,
220 pub seedling: String,
221 pub user_verification: String,
222}
223
224impl Configuration for Config {
225 fn db_config(&self) -> DatabaseConfig {
226 self.database.to_owned()
227 }
228}
229
230impl Default for Config {
231 fn default() -> Self {
232 Self {
233 name: default_name(),
234 database: default_database(),
235 service_hosts: ServiceHostsConfig::default(),
236 host: String::new(),
237 banned_usernames: default_banned_usernames(),
238 security: SecurityConfig::default(),
239 dirs: DirectoriesConfig::default(),
240 stripe: StripeConfig::default(),
241 turnstile: TurnstileConfig::default(),
242 }
243 }
244}
245
246impl Config {
247 pub fn read() -> Self {
249 toml::from_str(
250 &match std::fs::read_to_string(PathBufD::current().join("app.toml")) {
251 Ok(x) => x,
252 Err(_) => {
253 let x = Config::default();
254
255 std::fs::write(
256 PathBufD::current().join("app.toml"),
257 toml::to_string_pretty(&x).expect("failed to serialize config"),
258 )
259 .expect("failed to write config");
260
261 return x;
262 }
263 },
264 )
265 .expect("failed to deserialize config")
266 }
267}