diff --git a/Cargo.lock b/Cargo.lock index 93ffd280..44c91f69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3605,8 +3605,12 @@ dependencies = [ "async-std", "cached", "config", + "dotenv", "futures-locks", + "log", "once_cell", + "pretty_env_logger", + "sentry", "serde", ] @@ -3685,7 +3689,6 @@ dependencies = [ "revolt-database", "revolt-models", "revolt-permissions", - "revolt-quark", "revolt-result", "revolt_rocket_okapi", "rocket", diff --git a/crates/core/config/Cargo.toml b/crates/core/config/Cargo.toml index c8c5ed3b..82402449 100644 --- a/crates/core/config/Cargo.toml +++ b/crates/core/config/Cargo.toml @@ -14,6 +14,7 @@ default = ["test"] [dependencies] # Utility +dotenv = "0.15.0" config = "0.13.3" cached = "0.44.0" once_cell = "1.18.0" @@ -24,3 +25,10 @@ serde = { version = "1", features = ["derive"] } # Async futures-locks = "0.7.1" async-std = { version = "1.8.0", features = ["attributes"], optional = true } + +# Logging +log = "0.4.14" +pretty_env_logger = "0.4.0" + +# Sentry +sentry = "0.31.5" diff --git a/crates/core/config/Revolt.toml b/crates/core/config/Revolt.toml index dd63bf0e..e7514d47 100644 --- a/crates/core/config/Revolt.toml +++ b/crates/core/config/Revolt.toml @@ -1,3 +1,5 @@ +sentry_dsn = "" + [database] mongodb = "mongodb://database" redis = "redis://redis/" @@ -33,6 +35,7 @@ api_key = "" [api.security] authifier_shield_key = "" voso_legacy_token = "" +trust_cloudflare = false [api.security.captcha] hcaptcha_key = "" @@ -42,6 +45,7 @@ hcaptcha_sitekey = "" max_concurrent_connections = 50 [features] +webhooks_enabled = false [features.limits] diff --git a/crates/core/config/src/lib.rs b/crates/core/config/src/lib.rs index 61948e97..abaa5177 100644 --- a/crates/core/config/src/lib.rs +++ b/crates/core/config/src/lib.rs @@ -56,6 +56,9 @@ pub struct ApiSmtp { pub username: String, pub password: String, pub from_address: String, + pub reply_to: Option, + pub port: Option, + pub use_tls: Option, } #[derive(Deserialize, Debug, Clone)] @@ -80,6 +83,7 @@ pub struct ApiSecurity { pub authifier_shield_key: String, pub voso_legacy_token: String, pub captcha: ApiSecurityCaptcha, + pub trust_cloudflare: bool, } #[derive(Deserialize, Debug, Clone)] @@ -131,6 +135,7 @@ pub struct FeaturesLimitsCollection { #[derive(Deserialize, Debug, Clone)] pub struct Features { pub limits: FeaturesLimitsCollection, + pub webhooks_enabled: bool, } #[derive(Deserialize, Debug, Clone)] @@ -139,6 +144,31 @@ pub struct Settings { pub hosts: Hosts, pub api: Api, pub features: Features, + pub sentry_dsn: String, +} + +impl Settings { + pub fn preflight_checks(&self) { + if self.api.smtp.host.is_empty() { + #[cfg(not(debug_assertions))] + if !env::var("REVOLT_UNSAFE_NO_EMAIL").map_or(false, |v| v == *"1") { + panic!("Running in production without email is not recommended, set REVOLT_UNSAFE_NO_EMAIL=1 to override."); + } + + #[cfg(debug_assertions)] + log::warn!("No SMTP settings specified! Remember to configure email."); + } + + if self.api.security.captcha.hcaptcha_key.is_empty() { + #[cfg(not(debug_assertions))] + if !env::var("REVOLT_UNSAFE_NO_CAPTCHA").map_or(false, |v| v == *"1") { + panic!("Running in production without CAPTCHA is not recommended, set REVOLT_UNSAFE_NO_CAPTCHA=1 to override."); + } + + #[cfg(debug_assertions)] + log::warn!("No Captcha key specified! Remember to add hCaptcha key."); + } + } } pub async fn init() { @@ -157,6 +187,47 @@ pub async fn config() -> Settings { read().await.try_deserialize::().unwrap() } +/// Configure logging and common Rust variables +pub async fn setup_logging(release: &'static str) -> Option { + dotenv::dotenv().ok(); + + if std::env::var("RUST_LOG").is_err() { + std::env::set_var("RUST_LOG", "info"); + } + + if std::env::var("ROCKET_ADDRESS").is_err() { + std::env::set_var("ROCKET_ADDRESS", "0.0.0.0"); + } + + pretty_env_logger::init(); + log::info!("Starting {release}"); + + let config = config().await; + if config.sentry_dsn.is_empty() { + None + } else { + Some(sentry::init(( + config.sentry_dsn, + sentry::ClientOptions { + release: Some(release.into()), + ..Default::default() + }, + ))) + } +} + +#[macro_export] +macro_rules! configure { + () => { + let _sentry = $crate::setup_logging(concat!( + env!("CARGO_PKG_NAME"), + "@", + env!("CARGO_PKG_VERSION") + )) + .await; + }; +} + #[cfg(feature = "test")] #[cfg(test)] mod tests { diff --git a/crates/core/database/src/models/users/model.rs b/crates/core/database/src/models/users/model.rs index 5ae289a0..d60d90db 100644 --- a/crates/core/database/src/models/users/model.rs +++ b/crates/core/database/src/models/users/model.rs @@ -7,7 +7,7 @@ use rand::seq::SliceRandom; use revolt_config::config; use revolt_models::v0; use revolt_presence::filter_online; -use revolt_result::{create_error, Error, ErrorType, Result}; +use revolt_result::{create_error, Result}; use ulid::Ulid; auto_derived_partial!( diff --git a/crates/delta/Cargo.toml b/crates/delta/Cargo.toml index a02f427e..b6b45acd 100644 --- a/crates/delta/Cargo.toml +++ b/crates/delta/Cargo.toml @@ -65,9 +65,6 @@ rocket_prometheus = "0.10.0-rc.3" schemars = "0.8.8" revolt_rocket_okapi = { version = "0.9.1", features = ["swagger"] } -# quark -revolt-quark = { path = "../quark" } - # core authifier = "1.0.8" revolt-config = { path = "../core/config" } diff --git a/crates/delta/src/main.rs b/crates/delta/src/main.rs index a962ac9f..ee4957b5 100644 --- a/crates/delta/src/main.rs +++ b/crates/delta/src/main.rs @@ -8,6 +8,8 @@ extern crate serde_json; pub mod routes; pub mod util; +use revolt_config::config; +use revolt_database::events::client::EventV1; use revolt_database::{Database, MongoDb}; use rocket::{Build, Rocket}; use rocket_cors::{AllowedOrigins, CorsOptions}; @@ -16,19 +18,24 @@ use std::net::Ipv4Addr; use std::str::FromStr; use async_std::channel::unbounded; -use revolt_quark::authifier::{Authifier, AuthifierEvent}; -use revolt_quark::events::client::EventV1; -use revolt_quark::DatabaseInfo; +use authifier::config::{ + Captcha, Config as AuthifierConfig, EmailVerificationConfig, ResolveIp, SMTPSettings, Shield, + Template, Templates, +}; +use authifier::{Authifier, AuthifierEvent}; use rocket::data::ToByteUnit; pub async fn web() -> Rocket { + // Get settings + let config = config().await; + + // Ensure environment variables are present + config.preflight_checks(); + // Setup database let db = revolt_database::DatabaseInfo::Auto.connect().await.unwrap(); db.migrate_database().await.unwrap(); - // Legacy database setup from quark - let legacy_db = DatabaseInfo::Auto.connect().await.unwrap(); - // Setup Authifier event channel let (sender, receiver) = unbounded(); @@ -40,7 +47,8 @@ pub async fn web() -> Rocket { authifier::database::MongoDb(client.database("revolt")), ), }, - config: revolt_quark::util::authifier::config(), + config: Default::default(), + // config: authifier_config().await, event_channel: Some(sender), }; @@ -65,10 +73,6 @@ pub async fn web() -> Rocket { db.clone(), authifier.database.clone(), )); - async_std::task::spawn(revolt_quark::tasks::start_workers( - legacy_db.clone(), - authifier.database.clone(), - )); // Configure CORS let cors = CorsOptions { @@ -97,7 +101,7 @@ pub async fn web() -> Rocket { let rocket = rocket::build(); let prometheus = PrometheusMetrics::new(); - routes::mount(rocket) + routes::mount(config, rocket) .attach(prometheus.clone()) .mount("/metrics", prometheus) .mount("/", rocket_cors::catch_all_options_routes()) @@ -105,7 +109,6 @@ pub async fn web() -> Rocket { .mount("/swagger/", swagger) .manage(authifier) .manage(db) - .manage(legacy_db) .manage(cors.clone()) .attach(util::ratelimiter::RatelimitFairing) .attach(cors) @@ -116,13 +119,82 @@ pub async fn web() -> Rocket { }) } +pub async fn authifier_config() -> AuthifierConfig { + let config = config().await; + + let mut auth_config = AuthifierConfig { + email_verification: if !config.api.smtp.host.is_empty() { + EmailVerificationConfig::Enabled { + smtp: SMTPSettings { + from: config.api.smtp.from_address, + host: config.api.smtp.host, + username: config.api.smtp.username, + password: config.api.smtp.password, + reply_to: Some( + config + .api + .smtp + .reply_to + .unwrap_or("support@revolt.chat".into()), + ), + port: config.api.smtp.port, + use_tls: config.api.smtp.use_tls, + }, + expiry: Default::default(), + templates: Templates { + verify: Template { + title: "Verify your Revolt account.".into(), + text: include_str!("templates/verify.txt").into(), + url: format!("{}/login/verify/", config.hosts.app), + html: Some(include_str!("templates/verify.html").into()), + }, + reset: Template { + title: "Reset your Revolt password.".into(), + text: include_str!("templates/reset.txt").into(), + url: format!("{}/login/reset/", config.hosts.app), + html: Some(include_str!("templates/reset.html").into()), + }, + deletion: Template { + title: "Confirm account deletion.".into(), + text: include_str!("templates/deletion.txt").into(), + url: format!("{}/delete/", config.hosts.app), + html: Some(include_str!("templates/deletion.html").into()), + }, + welcome: None, + }, + } + } else { + EmailVerificationConfig::Disabled + }, + ..Default::default() + }; + + auth_config.invite_only = config.api.registration.invite_only; + + if !config.api.security.captcha.hcaptcha_key.is_empty() { + auth_config.captcha = Captcha::HCaptcha { + secret: config.api.security.captcha.hcaptcha_key, + }; + } + + if !config.api.security.authifier_shield_key.is_empty() { + auth_config.shield = Shield::Enabled { + api_key: config.api.security.authifier_shield_key, + strict: false, + }; + } + + if config.api.security.trust_cloudflare { + auth_config.resolve_ip = ResolveIp::Cloudflare; + } + + auth_config +} + #[launch] async fn rocket() -> _ { // Configure logging and environment - revolt_quark::configure!(); - - // Ensure environment variables are present - revolt_quark::variables::delta::preflight_checks(); + revolt_config::configure!(); // Start web server web().await diff --git a/crates/delta/src/routes/admin/mod.rs b/crates/delta/src/routes/admin/mod.rs deleted file mode 100644 index 053bf831..00000000 --- a/crates/delta/src/routes/admin/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi; -use rocket::Route; - -mod stats; - -pub fn routes() -> (Vec, OpenApi) { - openapi_get_routes_spec![stats::stats] -} diff --git a/crates/delta/src/routes/admin/stats.rs b/crates/delta/src/routes/admin/stats.rs deleted file mode 100644 index 1d043b03..00000000 --- a/crates/delta/src/routes/admin/stats.rs +++ /dev/null @@ -1,13 +0,0 @@ -use revolt_quark::models::stats::Stats; -use revolt_quark::{Db, Result}; - -use rocket::serde::json::Json; - -/// # Query Stats -/// -/// Fetch various technical statistics. -#[openapi(tag = "Admin")] -#[get("/stats")] -pub async fn stats(db: &Db) -> Result> { - Ok(Json(db.generate_stats().await?)) -} diff --git a/crates/delta/src/routes/channels/message_edit.rs b/crates/delta/src/routes/channels/message_edit.rs index 1966cef7..4c1a78b9 100644 --- a/crates/delta/src/routes/channels/message_edit.rs +++ b/crates/delta/src/routes/channels/message_edit.rs @@ -1,6 +1,7 @@ use iso8601_timestamp::Timestamp; use revolt_config::config; use revolt_database::{ + tasks, util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, Message, PartialMessage, User, }; @@ -88,7 +89,7 @@ pub async fn edit( // Queue up a task for processing embeds if the we have sufficient permissions if permissions.has_channel_permission(ChannelPermission::SendEmbeds) { if let Some(content) = edit.content { - revolt_quark::tasks::process_embeds::queue( + tasks::process_embeds::queue( message.channel.to_string(), message.id.to_string(), content, diff --git a/crates/delta/src/routes/mod.rs b/crates/delta/src/routes/mod.rs index b9b0fac0..516c2166 100644 --- a/crates/delta/src/routes/mod.rs +++ b/crates/delta/src/routes/mod.rs @@ -1,10 +1,9 @@ -use revolt_quark::variables::delta::IS_STAGING; +use revolt_config::{config, Settings}; use revolt_rocket_okapi::{revolt_okapi::openapi3::OpenApi, settings::OpenApiSettings}; pub use rocket::http::Status; pub use rocket::response::Redirect; use rocket::{Build, Rocket}; -mod admin; mod bots; mod channels; mod customisation; @@ -18,15 +17,14 @@ mod sync; mod users; mod webhooks; -pub fn mount(mut rocket: Rocket) -> Rocket { +pub fn mount(config: Settings, mut rocket: Rocket) -> Rocket { let settings = OpenApiSettings::default(); - if *IS_STAGING { + if config.features.webhooks_enabled { mount_endpoints_and_merged_docs! { rocket, "/".to_owned(), settings, "/" => (vec![], custom_openapi_spec()), "" => openapi_get_routes_spec![root::root], - "/admin" => admin::routes(), "/users" => users::routes(), "/bots" => bots::routes(), "/channels" => channels::routes(), @@ -47,7 +45,6 @@ pub fn mount(mut rocket: Rocket) -> Rocket { rocket, "/".to_owned(), settings, "/" => (vec![], custom_openapi_spec()), "" => openapi_get_routes_spec![root::root], - "/admin" => admin::routes(), "/users" => users::routes(), "/bots" => bots::routes(), "/channels" => channels::routes(), diff --git a/crates/delta/src/routes/onboard/complete.rs b/crates/delta/src/routes/onboard/complete.rs index bc20aa97..93846013 100644 --- a/crates/delta/src/routes/onboard/complete.rs +++ b/crates/delta/src/routes/onboard/complete.rs @@ -1,8 +1,8 @@ +use authifier::models::Session; use once_cell::sync::Lazy; use regex::Regex; use revolt_database::{Database, User}; use revolt_models::v0; -use revolt_quark::authifier::models::Session; use revolt_result::{create_error, Result}; use rocket::{serde::json::Json, State}; diff --git a/crates/delta/src/routes/root.rs b/crates/delta/src/routes/root.rs index f506dd0d..1e237bff 100644 --- a/crates/delta/src/routes/root.rs +++ b/crates/delta/src/routes/root.rs @@ -1,9 +1,5 @@ -use revolt_quark::variables::delta::{ - APP_URL, AUTUMN_URL, EXTERNAL_WS_URL, HCAPTCHA_SITEKEY, INVITE_ONLY, JANUARY_URL, USE_AUTUMN, - USE_EMAIL, USE_HCAPTCHA, USE_JANUARY, USE_VOSO, VAPID_PUBLIC_KEY, VOSO_URL, VOSO_WS_HOST, -}; -use revolt_quark::Result; - +use revolt_config::config; +use revolt_result::Result; use rocket::serde::json::Json; use serde::Serialize; @@ -91,32 +87,34 @@ pub struct RevoltConfig { #[openapi(tag = "Core")] #[get("/")] pub async fn root() -> Result> { + let config = config().await; + Ok(Json(RevoltConfig { revolt: env!("CARGO_PKG_VERSION").to_string(), features: RevoltFeatures { captcha: CaptchaFeature { - enabled: *USE_HCAPTCHA, - key: HCAPTCHA_SITEKEY.to_string(), + enabled: !config.api.security.captcha.hcaptcha_key.is_empty(), + key: config.api.security.captcha.hcaptcha_sitekey, }, - email: *USE_EMAIL, - invite_only: *INVITE_ONLY, + email: !config.api.smtp.host.is_empty(), + invite_only: config.api.registration.invite_only, autumn: Feature { - enabled: *USE_AUTUMN, - url: AUTUMN_URL.to_string(), + enabled: !config.hosts.autumn.is_empty(), + url: config.hosts.autumn, }, january: Feature { - enabled: *USE_JANUARY, - url: JANUARY_URL.to_string(), + enabled: !config.hosts.january.is_empty(), + url: config.hosts.january, }, voso: VoiceFeature { - enabled: *USE_VOSO, - url: VOSO_URL.to_string(), - ws: VOSO_WS_HOST.to_string(), + enabled: !config.hosts.voso_legacy.is_empty(), + url: config.hosts.voso_legacy, + ws: config.hosts.voso_legacy_ws, }, }, - ws: EXTERNAL_WS_URL.to_string(), - app: APP_URL.to_string(), - vapid: VAPID_PUBLIC_KEY.to_string(), + ws: config.hosts.events, + app: config.hosts.app, + vapid: config.api.vapid.public_key, build: BuildInformation { commit_sha: option_env!("VERGEN_GIT_SHA") .unwrap_or_else(|| "") diff --git a/crates/delta/src/routes/users/avatars/1.png b/crates/delta/src/routes/users/avatars/1.png new file mode 100644 index 00000000..88d2e28b Binary files /dev/null and b/crates/delta/src/routes/users/avatars/1.png differ diff --git a/crates/delta/src/routes/users/avatars/2.png b/crates/delta/src/routes/users/avatars/2.png new file mode 100644 index 00000000..dd0d2967 Binary files /dev/null and b/crates/delta/src/routes/users/avatars/2.png differ diff --git a/crates/delta/src/routes/users/avatars/3.png b/crates/delta/src/routes/users/avatars/3.png new file mode 100644 index 00000000..c40c1291 Binary files /dev/null and b/crates/delta/src/routes/users/avatars/3.png differ diff --git a/crates/delta/src/routes/users/avatars/4.png b/crates/delta/src/routes/users/avatars/4.png new file mode 100644 index 00000000..6db7af60 Binary files /dev/null and b/crates/delta/src/routes/users/avatars/4.png differ diff --git a/crates/delta/src/routes/users/avatars/5.png b/crates/delta/src/routes/users/avatars/5.png new file mode 100644 index 00000000..9f32511c Binary files /dev/null and b/crates/delta/src/routes/users/avatars/5.png differ diff --git a/crates/delta/src/routes/users/avatars/6.png b/crates/delta/src/routes/users/avatars/6.png new file mode 100644 index 00000000..533f920d Binary files /dev/null and b/crates/delta/src/routes/users/avatars/6.png differ diff --git a/crates/delta/src/routes/users/avatars/7.png b/crates/delta/src/routes/users/avatars/7.png new file mode 100644 index 00000000..7d9ffd0e Binary files /dev/null and b/crates/delta/src/routes/users/avatars/7.png differ diff --git a/crates/delta/src/routes/users/get_default_avatar.rs b/crates/delta/src/routes/users/get_default_avatar.rs index 8bd32e2a..193d291c 100644 --- a/crates/delta/src/routes/users/get_default_avatar.rs +++ b/crates/delta/src/routes/users/get_default_avatar.rs @@ -59,6 +59,14 @@ impl revolt_rocket_okapi::response::OpenApiResponderInner for CachedFile { pub async fn default_avatar(target: String) -> CachedFile { CachedFile(( ContentType::PNG, - revolt_quark::util::pfp::avatar(target.chars().last().unwrap()), + match target.chars().last().unwrap() { + '0' | '1' | '2' | '3' | 'S' | 'Z' => include_bytes!("avatars/2.png").to_vec(), + '4' | '5' | '6' | '7' | 'T' => include_bytes!("avatars/3.png").to_vec(), + '8' | '9' | 'A' | 'B' => include_bytes!("avatars/4.png").to_vec(), + 'C' | 'D' | 'E' | 'F' | 'V' => include_bytes!("avatars/5.png").to_vec(), + 'G' | 'H' | 'J' | 'K' | 'W' => include_bytes!("avatars/6.png").to_vec(), + 'M' | 'N' | 'P' | 'Q' | 'X' => include_bytes!("avatars/7.png").to_vec(), + _ => include_bytes!("avatars/1.png").to_vec(), + }, )) } diff --git a/crates/delta/src/templates/deletion.html b/crates/delta/src/templates/deletion.html new file mode 100644 index 00000000..e18b1d8a --- /dev/null +++ b/crates/delta/src/templates/deletion.html @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/crates/delta/src/templates/deletion.original.html b/crates/delta/src/templates/deletion.original.html new file mode 100644 index 00000000..1028ce49 --- /dev/null +++ b/crates/delta/src/templates/deletion.original.html @@ -0,0 +1,30 @@ + + + + + + +
+ Revolt Logo +
+

Account Deletion

+

+ You requested to have your account deleted, if you did not perform + this action please take measures to secure your account immediately. +

+ Confirm +
+
+ This email is intended for {{email}}
+ Sent from Revolt
+ Made in the EU +
+
+ + diff --git a/crates/delta/src/templates/deletion.txt b/crates/delta/src/templates/deletion.txt new file mode 100644 index 00000000..88112b8e --- /dev/null +++ b/crates/delta/src/templates/deletion.txt @@ -0,0 +1,7 @@ +You requested to have your account deleted, if you did not perform this action please take measures to secure your account immediately. + +Please navigate to: {{url}} + +This email is intended for {{email}} +Sent by Revolt +Made in the EU diff --git a/crates/delta/src/templates/reset.html b/crates/delta/src/templates/reset.html new file mode 100644 index 00000000..6c4da8f6 --- /dev/null +++ b/crates/delta/src/templates/reset.html @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/crates/delta/src/templates/reset.original.html b/crates/delta/src/templates/reset.original.html new file mode 100644 index 00000000..f40c7254 --- /dev/null +++ b/crates/delta/src/templates/reset.original.html @@ -0,0 +1,26 @@ + + + + + + +
+ +
+

Password Reset

+

You requested a password reset, click below to continue.

+ Reset +
+
+ This email is intended for {{email}}
+ Sent from Revolt
+ Made in the EU +
+
+ + diff --git a/crates/delta/src/templates/reset.txt b/crates/delta/src/templates/reset.txt new file mode 100644 index 00000000..fdc2751f --- /dev/null +++ b/crates/delta/src/templates/reset.txt @@ -0,0 +1,7 @@ +You requested a password reset, if you did not perform this action you can safely ignore this email. + +Please navigate to: {{url}} + +This email is intended for {{email}} +Sent by Revolt +Made in the EU diff --git a/crates/delta/src/templates/verify.html b/crates/delta/src/templates/verify.html new file mode 100644 index 00000000..d7016f62 --- /dev/null +++ b/crates/delta/src/templates/verify.html @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/crates/delta/src/templates/verify.original.html b/crates/delta/src/templates/verify.original.html new file mode 100644 index 00000000..e3ce0d5c --- /dev/null +++ b/crates/delta/src/templates/verify.original.html @@ -0,0 +1,27 @@ + + + + + + +
+ Revolt Logo +
+

Almost there!

+

To complete your sign up, we just need to verify your email.

+ Confirm +
+
+ This email is intended for {{email}}
+ Sent from Revolt
+ Made in the EU +
+
+ + diff --git a/crates/delta/src/templates/verify.txt b/crates/delta/src/templates/verify.txt new file mode 100644 index 00000000..1fdaaa63 --- /dev/null +++ b/crates/delta/src/templates/verify.txt @@ -0,0 +1,8 @@ +Almost there! +To complete your sign up, we just need to verify your email. + +Please navigate to: {{url}} + +This email is intended for {{email}} +Sent by Revolt +Made in the EU diff --git a/crates/delta/src/util/ratelimiter.rs b/crates/delta/src/util/ratelimiter.rs index df89e899..ce7317ff 100644 --- a/crates/delta/src/util/ratelimiter.rs +++ b/crates/delta/src/util/ratelimiter.rs @@ -3,7 +3,7 @@ use std::hash::Hasher; use std::ops::Add; use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use revolt_quark::authifier::models::Session; +use authifier::models::Session; use rocket::fairing::{Fairing, Info, Kind}; use rocket::http::uri::Origin; use rocket::http::{Method, Status}; diff --git a/crates/delta/src/util/test.rs b/crates/delta/src/util/test.rs index 250b8537..428f8bbb 100644 --- a/crates/delta/src/util/test.rs +++ b/crates/delta/src/util/test.rs @@ -1,12 +1,12 @@ +use authifier::{ + models::{Account, Session}, + Authifier, +}; use futures::StreamExt; use rand::Rng; use redis_kiss::redis::aio::PubSub; use revolt_database::{events::client::EventV1, Database, User}; use revolt_models::v0; -use revolt_quark::authifier::{ - models::{Account, Session}, - Authifier, -}; use rocket::local::asynchronous::Client; pub struct TestHarness {