-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.rs
204 lines (148 loc) · 5.59 KB
/
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//! The config of VOxOV is fully static, therefore lock-free.
//! A restart is required to update any config.
//! To avoid interruption, prepend a load balancer.
use crate::{gene::GeneMeta, to_static};
use serde::Serialize;
use std::collections::HashMap;
use std::net::IpAddr;
use std::{
env,
net::{Ipv4Addr, SocketAddr},
};
/// Static config struct. Modification requires relaunch.
/// All constants are from environment variables.
#[derive(Serialize)]
pub struct Config {
/// Source code. AGPL.
pub source_code: String,
/// Redis URI.
#[serde(skip_serializing)]
pub redis_addr: String,
/// MongoDB URI.
#[serde(skip_serializing)]
pub mongo_addr: String,
/// Ripperd handles meme expiration.
/// 0 or unset for false, others for true.
pub ripperd_disabled: bool,
/// Ripperd's interval as seconds between meme rips.
pub ripperd_interval: u64,
/// S3 or compatible object storage URI.
#[serde(skip_serializing)]
pub s3_addr: String,
/// S3 or compativle objest storage region.
pub s3_region: String,
/// S3 access key.
#[serde(skip_serializing)]
pub s3_access_key: String,
/// S3 secret key.
#[serde(skip_serializing)]
pub s3_secret_key: String,
/// Reset instance on resource draining.
pub samsara: bool,
/// Endpoint API in http.
pub http_addr: SocketAddr,
// graphql_addr
/// Seconds before access token expire.
pub access_ttl: i64,
/// Seconds before refresh token expire.
pub refresh_ttl: i64,
/// Seconds before user account expire.
pub user_ttl: i64,
/// Minimum credit.
pub credit_limit: i64,
/// Credit retention
pub credit_retention: u64,
/// Cost per millisecond.
pub time_cost: i64,
/// Cost per KB per day in MongoDB.
pub space_cost_doc: i64,
/// Cost per KB per day in S3.
pub space_cost_obj: i64,
/// Cost per byte.
pub traffic_cost: i64,
/// Check-in award.
pub check_in_award: i64,
/// Seconds before check-in refresh.
pub check_in_refresh: i64,
/// SMS receivers for authentication.
pub auth_phones: &'static Vec<String>,
/// Skip auth.
pub skip_auth: bool,
/// Registered genes.
pub gene_metas: &'static HashMap<String, GeneMeta>,
//pub fed_members: &'static HashMap<Id, String>,
}
/// Default port for http endpoint.
const DEFAULT_HTTP_PORT: u16 = 8080;
/// Changing this constant invalidates all phone numbers!!
pub const PHONE_MAX_BYTES: usize = 16;
/// Set an entry by environment variable, or use the default.
macro_rules! env_or {
($e:literal, $d:expr) => {
match env::var($e) {
Ok(var) => var.parse().unwrap(),
Err(_) => $d.into(),
}
};
}
/// '0' or unset is false, otherwise is true.
macro_rules! env_bool {
($e:literal) => {
match env::var($e) {
Ok(x) if x == "0" => false,
Ok(_) => true,
_ => false,
}
};
}
impl Config {
pub fn new() -> Config {
Config {
source_code: env_or!("SOURCE_CODE", "https://github.com/vorgv/voxov"),
redis_addr: env_or!("REDIS_ADDR", "redis://localhost/"),
mongo_addr: env_or!("MONGO_ADDR", "mongodb://127.0.0.1:27017/"),
ripperd_disabled: env_bool!("RIPPERD_DISABLED"),
ripperd_interval: env_or!("RIPPERD_INTERVAL", 60_u64), // seconds
s3_addr: env_or!("S3_ADDR", "http://127.0.0.1:9000"),
s3_region: env_or!("S3_REGION", "develop"),
s3_access_key: env_or!("S3_ACCESS_KEY", "example-user"),
s3_secret_key: env_or!("S3_SECRET_KEY", "example-password"),
samsara: env_bool!("SAMSARA"),
http_addr: match env::var("HTTP_ADDR") {
Ok(var) => SocketAddr::parse_ascii(var.as_bytes()).unwrap(),
Err(_) => {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), DEFAULT_HTTP_PORT)
}
},
access_ttl: env_or!("ACCESS_TTL", 60 * 60_i64), // one hour
refresh_ttl: env_or!("REFRESH_TTL", 60 * 60 * 24 * 30_i64), // one month
user_ttl: env_or!("USER_TTL", 60 * 60 * 24 * 365 * 5_i64), // five years
credit_limit: env_or!("CREDIT_LIMIT", -10_000_000_000_i64), // one USD
credit_retention: env_or!("CREDIT_RETENTION", 60 * 60 * 24 * 365 * 5_u64), // five years
time_cost: env_or!("TIME_COST", 1_000_i64), // per millisecond
space_cost_doc: env_or!("SPACE_COST_DOC", 100_i64), // per KB per day
space_cost_obj: env_or!("SPACE_COST_OBJ", 10_i64), // per KB per day
traffic_cost: env_or!("TRAFFIC_COST", 1_i64), // per byte outbound
check_in_award: env_or!("CHECK_IN_AWARD", 10_000_000_i64), // 1 GB/day storage
check_in_refresh: env_or!("CHECK_IN_REFRESH", 60 * 60 * 24_i64), // 1 check-in/day
auth_phones: to_static!(match env::var("AUTH_PHONES") {
Ok(var) => {
let ap: Vec<_> = var.split(':').map(String::from).collect();
let max_bytes = ap.iter().map(|s| s.as_bytes().len()).max().unwrap();
if max_bytes > PHONE_MAX_BYTES {
panic!("Phone number too long")
}
ap
}
Err(_) => vec!["12345".to_string(), "67890".to_string()],
}),
skip_auth: env_bool!("SKIP_AUTH"),
gene_metas: to_static!(GeneMeta::new_map()),
}
}
}
impl Default for Config {
fn default() -> Self {
Config::new()
}
}