Merge branch 'main' into feat/admin-api
# Conflicts: # crates/core/database/src/drivers/mod.rs # crates/core/database/src/drivers/reference.rs # crates/core/database/src/models/admin_migrations/ops/mongodb/init.rs # crates/core/database/src/models/channels/ops.rs # crates/core/database/src/models/server_members/ops.rs # crates/core/database/src/models/server_members/ops/mongodb.rs # crates/core/database/src/models/server_members/ops/reference.rs # crates/core/database/src/util/bridge/v0.rs # crates/core/result/src/axum.rs # crates/core/result/src/lib.rs # crates/core/result/src/rocket.rs # crates/delta/src/routes/mod.rs # crates/delta/src/routes/servers/server_edit.rs
This commit is contained in:
@@ -13,21 +13,20 @@ repository = "https://github.com/stoatchat/stoatchat"
|
||||
anyhow = ["dep:sentry-anyhow"]
|
||||
report-macros = ["revolt-result"]
|
||||
sentry = ["dep:sentry"]
|
||||
test = ["async-std"]
|
||||
default = ["test", "sentry"]
|
||||
test = ["tokio"]
|
||||
default = ["sentry"]
|
||||
|
||||
[dependencies]
|
||||
# Utility
|
||||
config = { workspace = true }
|
||||
cached = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
|
||||
# Serde
|
||||
serde = { workspace = true }
|
||||
|
||||
# Async
|
||||
futures-locks = { workspace = true }
|
||||
async-std = { workspace = true, features = ["attributes"], optional = true }
|
||||
tokio = { workspace = true, optional = true }
|
||||
|
||||
# Logging
|
||||
log = { workspace = true }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
environment = "test"
|
||||
|
||||
[database]
|
||||
mongodb = "mongodb://localhost"
|
||||
redis = "redis://localhost/"
|
||||
@@ -10,3 +12,12 @@ password = "rabbitpass"
|
||||
|
||||
[features]
|
||||
webhooks_enabled = true
|
||||
|
||||
[api.smtp]
|
||||
host = "localhost"
|
||||
username = "smtp"
|
||||
password = "smtp"
|
||||
from_address = "development@stoat.chat"
|
||||
reply_to = "support@stoat.chat"
|
||||
port = 14025
|
||||
use_tls = false
|
||||
@@ -1,5 +1,6 @@
|
||||
production = false
|
||||
disable_events_dont_use = false
|
||||
environment = "dev"
|
||||
|
||||
[database]
|
||||
# MongoDB connection URL
|
||||
@@ -53,6 +54,10 @@ from_address = "noreply@example.com"
|
||||
# port = 587
|
||||
# use_tls = true
|
||||
|
||||
[api.smtp.expiry]
|
||||
expire_verification = 604800 # 3600 * 24 * 7
|
||||
expire_password_reset = 86400 # 3600 * 24
|
||||
expire_account_deletion = 86400 # 3600 * 24
|
||||
|
||||
[api.security]
|
||||
# Authifier Shield API key
|
||||
@@ -74,6 +79,10 @@ admin_keys = []
|
||||
hcaptcha_key = ""
|
||||
hcaptcha_sitekey = ""
|
||||
|
||||
[api.security.shield]
|
||||
host = ""
|
||||
key = ""
|
||||
|
||||
[api.workers]
|
||||
# Maximum concurrent connections (to proxy server)
|
||||
max_concurrent_connections = 50
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::{collections::HashMap, path::Path};
|
||||
#[cfg(feature = "test")]
|
||||
use std::sync::OnceLock;
|
||||
use std::{collections::HashMap, path::Path, sync::LazyLock};
|
||||
|
||||
use cached::proc_macro::cached;
|
||||
use config::{Config, Environment, File, FileFormat};
|
||||
use futures_locks::RwLock;
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[cfg(feature = "sentry")]
|
||||
@@ -66,13 +67,28 @@ static CONFIG_SEARCH_PATHS: [&str; 3] = [
|
||||
static TEST_OVERRIDE_PATH: &str = "Revolt.test-overrides.toml";
|
||||
|
||||
/// Configuration builder
|
||||
static CONFIG_BUILDER: Lazy<RwLock<Config>> = Lazy::new(|| {
|
||||
static CONFIG_BUILDER: LazyLock<RwLock<Config>> = LazyLock::new(|| {
|
||||
RwLock::new({
|
||||
let mut builder = Config::builder().add_source(File::from_str(
|
||||
include_str!("../Revolt.toml"),
|
||||
FileFormat::Toml,
|
||||
));
|
||||
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
let mut cwd: Option<&Path> = Some(&cwd);
|
||||
|
||||
while let Some(path) = cwd {
|
||||
for config_path in CONFIG_SEARCH_PATHS {
|
||||
let config_path = path.join(config_path);
|
||||
if config_path.exists() {
|
||||
builder = builder
|
||||
.add_source(File::new(config_path.to_str().unwrap(), FileFormat::Toml));
|
||||
}
|
||||
}
|
||||
|
||||
cwd = path.parent();
|
||||
}
|
||||
|
||||
if std::env::var("TEST_DB").is_ok() {
|
||||
builder = builder.add_source(File::from_str(
|
||||
include_str!("../Revolt.test.toml"),
|
||||
@@ -94,21 +110,6 @@ static CONFIG_BUILDER: Lazy<RwLock<Config>> = Lazy::new(|| {
|
||||
}
|
||||
}
|
||||
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
let mut cwd: Option<&Path> = Some(&cwd);
|
||||
|
||||
while let Some(path) = cwd {
|
||||
for config_path in CONFIG_SEARCH_PATHS {
|
||||
let config_path = path.join(config_path);
|
||||
if config_path.exists() {
|
||||
builder = builder
|
||||
.add_source(File::new(config_path.to_str().unwrap(), FileFormat::Toml));
|
||||
}
|
||||
}
|
||||
|
||||
cwd = path.parent();
|
||||
}
|
||||
|
||||
builder = builder.add_source(Environment::with_prefix("REVOLT").separator("__"));
|
||||
|
||||
builder.build().unwrap()
|
||||
@@ -162,6 +163,18 @@ pub struct ApiSmtp {
|
||||
pub port: Option<i32>,
|
||||
pub use_tls: Option<bool>,
|
||||
pub use_starttls: Option<bool>,
|
||||
pub expiry: EmailExpiry,
|
||||
}
|
||||
|
||||
/// Email expiration config
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct EmailExpiry {
|
||||
/// How long email verification codes should last for (in seconds)
|
||||
pub expire_verification: i64,
|
||||
/// How long password reset codes should last for (in seconds)
|
||||
pub expire_password_reset: i64,
|
||||
/// How long account deletion codes should last for (in seconds)
|
||||
pub expire_account_deletion: i64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
@@ -201,9 +214,15 @@ pub struct ApiSecurityCaptcha {
|
||||
pub hcaptcha_sitekey: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct ApiSecurityShield {
|
||||
pub host: String,
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct ApiSecurity {
|
||||
pub authifier_shield_key: String,
|
||||
pub shield: ApiSecurityShield,
|
||||
pub voso_legacy_token: String,
|
||||
pub captcha: ApiSecurityCaptcha,
|
||||
pub trust_cloudflare: bool,
|
||||
@@ -452,6 +471,7 @@ pub struct Settings {
|
||||
pub features: Features,
|
||||
pub sentry: Sentry,
|
||||
pub production: bool,
|
||||
pub environment: String,
|
||||
pub disable_events_dont_use: bool,
|
||||
}
|
||||
|
||||
@@ -478,8 +498,7 @@ pub async fn read() -> Config {
|
||||
CONFIG_BUILDER.read().await.clone()
|
||||
}
|
||||
|
||||
#[cached(time = 30)]
|
||||
pub async fn config() -> Settings {
|
||||
pub async fn config_no_cache() -> Settings {
|
||||
let mut config = read().await.try_deserialize::<Settings>().unwrap();
|
||||
|
||||
// inject REDIS_URI for redis-kiss library
|
||||
@@ -497,6 +516,34 @@ pub async fn config() -> Settings {
|
||||
config
|
||||
}
|
||||
|
||||
#[cached(time = 30)]
|
||||
pub async fn config() -> Settings {
|
||||
#[cfg(feature = "test")]
|
||||
if let Some(overwrites) = CONFIG_OVERWRITES.get() {
|
||||
return overwrites.clone();
|
||||
}
|
||||
|
||||
config_no_cache().await
|
||||
}
|
||||
|
||||
#[cfg(feature = "test")]
|
||||
static CONFIG_OVERWRITES: OnceLock<Settings> = OnceLock::new();
|
||||
|
||||
/// Modify the config values for a test, this can only be called once
|
||||
///
|
||||
/// This will also fail if two or more tests are running in the same process and both try to modify the config,
|
||||
/// This could happen if tests where run under `cargo test` instead of `nextest`.
|
||||
#[cfg(feature = "test")]
|
||||
pub async fn overwrite_config(f: impl FnOnce(&mut Settings)) {
|
||||
let mut config = config_no_cache().await;
|
||||
|
||||
f(&mut config);
|
||||
|
||||
CONFIG_OVERWRITES.set(config).expect(
|
||||
"Cannot overwrite config multiple times, make sure you are running tests through nextest.",
|
||||
);
|
||||
}
|
||||
|
||||
/// Configure logging and common Rust variables
|
||||
#[cfg(feature = "sentry")]
|
||||
pub async fn setup_logging(release: &'static str, dsn: String) -> Option<sentry::ClientInitGuard> {
|
||||
@@ -542,7 +589,7 @@ macro_rules! configure {
|
||||
mod tests {
|
||||
use crate::init;
|
||||
|
||||
#[async_std::test]
|
||||
#[tokio::test]
|
||||
async fn it_works() {
|
||||
init().await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user