diff --git a/Cargo.lock b/Cargo.lock index 256b947f..2e9d3b77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6535,7 +6535,6 @@ dependencies = [ "bson", "deadqueue", "decancer", - "fcm_v1", "futures", "indexmap 1.9.3", "isahc", @@ -6558,7 +6557,6 @@ dependencies = [ "revolt-permissions", "revolt-presence", "revolt-result", - "revolt_a2", "revolt_okapi", "revolt_optional_struct", "revolt_rocket_okapi", @@ -6570,7 +6568,6 @@ dependencies = [ "unicode-segmentation", "url-escape", "validator 0.16.1", - "web-push", ] [[package]] diff --git a/compose.yml b/compose.yml index 31af45ba..89b29594 100644 --- a/compose.yml +++ b/compose.yml @@ -34,7 +34,7 @@ services: - minio entrypoint: > /bin/sh -c "while ! /usr/bin/mc ready minio; do - /usr/bin/mc config host add minio http://minio:9000 minioautumn minioautumn; + /usr/bin/mc alias set minio http://minio:9000 minioautumn minioautumn; echo 'Waiting minio...' && sleep 1; done; /usr/bin/mc mb minio/revolt-uploads; exit 0;" diff --git a/crates/core/config/Cargo.toml b/crates/core/config/Cargo.toml index 04cf6fca..26cc1c25 100644 --- a/crates/core/config/Cargo.toml +++ b/crates/core/config/Cargo.toml @@ -11,8 +11,9 @@ description = "Revolt Backend: Configuration" [features] anyhow = ["dep:sentry-anyhow"] report-macros = ["revolt-result"] +sentry = ["dep:sentry"] test = ["async-std"] -default = ["test", "anyhow"] +default = ["test", "sentry"] [dependencies] # Utility @@ -32,7 +33,7 @@ log = "0.4.14" pretty_env_logger = "0.4.0" # Sentry -sentry = "0.31.5" +sentry = { version = "0.31.5", optional = true } sentry-anyhow = { version = "0.38.1", optional = true } # Core diff --git a/crates/core/config/src/lib.rs b/crates/core/config/src/lib.rs index 5d8c0998..93df9c11 100644 --- a/crates/core/config/src/lib.rs +++ b/crates/core/config/src/lib.rs @@ -6,10 +6,12 @@ use futures_locks::RwLock; use once_cell::sync::Lazy; use serde::Deserialize; +#[cfg(feature = "sentry")] pub use sentry::{capture_error, capture_message, Level}; +#[cfg(feature = "anyhow")] pub use sentry_anyhow::capture_anyhow; -#[cfg(feature = "report-macros")] +#[cfg(all(feature = "report-macros", feature = "sentry"))] #[macro_export] macro_rules! report_error { ( $expr: expr, $error: ident $( $tt:tt )? ) => { @@ -24,7 +26,7 @@ macro_rules! report_error { }; } -#[cfg(feature = "report-macros")] +#[cfg(all(feature = "report-macros", feature = "sentry"))] #[macro_export] macro_rules! capture_internal_error { ( $expr: expr ) => { @@ -35,7 +37,7 @@ macro_rules! capture_internal_error { }; } -#[cfg(feature = "report-macros")] +#[cfg(all(feature = "report-macros", feature = "sentry"))] #[macro_export] macro_rules! report_internal_error { ( $expr: expr ) => { @@ -442,6 +444,7 @@ pub async fn config() -> Settings { } /// Configure logging and common Rust variables +#[cfg(feature = "sentry")] pub async fn setup_logging(release: &'static str, dsn: String) -> Option { if std::env::var("RUST_LOG").is_err() { std::env::set_var("RUST_LOG", "info"); @@ -467,6 +470,7 @@ pub async fn setup_logging(release: &'static str, dsn: String) -> Option { diff --git a/crates/core/database/Cargo.toml b/crates/core/database/Cargo.toml index 7794b0d7..59c3fbb8 100644 --- a/crates/core/database/Cargo.toml +++ b/crates/core/database/Cargo.toml @@ -10,12 +10,12 @@ description = "Revolt Backend: Database Implementation" [features] # Databases -mongodb = ["dep:mongodb", "bson"] +mongodb = ["dep:mongodb", "bson", "authifier/database-mongodb"] # ... Other tasks = ["isahc", "linkify", "url-escape"] -async-std-runtime = ["async-std"] -rocket-impl = ["rocket", "schemars", "revolt_okapi", "revolt_rocket_okapi"] +async-std-runtime = ["async-std", "authifier/async-std-runtime"] +rocket-impl = ["rocket", "schemars", "revolt_okapi", "revolt_rocket_okapi", "authifier/rocket_impl"] axum-impl = ["axum"] redis-is-patched = ["revolt-presence/redis-is-patched"] @@ -91,13 +91,8 @@ rocket = { version = "0.5.1", default-features = false, features = [ revolt_okapi = { version = "0.9.1", optional = true } revolt_rocket_okapi = { version = "0.10.0", optional = true } -# Notifications -fcm_v1 = "0.3.0" -web-push = "0.10.0" -revolt_a2 = { version = "0.10", default-features = false, features = ["ring"] } - # Authifier -authifier = { version = "1.0.15", features = ["rocket_impl"] } +authifier = { version = "1.0.15" } # RabbitMQ amqprs = { version = "1.7.0" } diff --git a/crates/core/database/src/drivers/mod.rs b/crates/core/database/src/drivers/mod.rs index e0573484..9618ee13 100644 --- a/crates/core/database/src/drivers/mod.rs +++ b/crates/core/database/src/drivers/mod.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "mongodb")] mod mongodb; mod reference; @@ -13,6 +14,7 @@ use authifier::Authifier; use rand::Rng; use revolt_config::config; +#[cfg(feature = "mongodb")] pub use self::mongodb::*; pub use self::reference::*; @@ -25,8 +27,10 @@ pub enum DatabaseInfo { /// Use the mock database Reference, /// Connect to MongoDB + #[cfg(feature = "mongodb")] MongoDb { uri: String, database_name: String }, /// Use existing MongoDB connection + #[cfg(feature = "mongodb")] MongoDbFromClient(::mongodb::Client, String), } @@ -36,6 +40,7 @@ pub enum Database { /// Mock database Reference(ReferenceDb), /// MongoDB database + #[cfg(feature = "mongodb")] MongoDb(MongoDb), } @@ -45,7 +50,7 @@ impl DatabaseInfo { pub async fn connect(self) -> Result { let config = config().await; - Ok(match self { + match self { DatabaseInfo::Auto => { if std::env::var("TEST_DB").is_ok() { DatabaseInfo::Test(format!( @@ -53,16 +58,20 @@ impl DatabaseInfo { rand::thread_rng().gen_range(1_000_000..10_000_000) )) .connect() - .await? + .await } else if !config.database.mongodb.is_empty() { - DatabaseInfo::MongoDb { + #[cfg(feature = "mongodb")] + return DatabaseInfo::MongoDb { uri: config.database.mongodb, database_name: "revolt".to_string(), } .connect() - .await? + .await; + + #[cfg(not(feature = "mongodb"))] + return Err("MongoDB not enabled.".to_string()) } else { - DatabaseInfo::Reference.connect().await? + DatabaseInfo::Reference.connect().await } } DatabaseInfo::Test(database_name) => { @@ -70,30 +79,36 @@ impl DatabaseInfo { .expect("`TEST_DB` environment variable should be set to REFERENCE or MONGODB") .as_str() { - "REFERENCE" => DatabaseInfo::Reference.connect().await?, + "REFERENCE" => DatabaseInfo::Reference.connect().await, "MONGODB" => { - DatabaseInfo::MongoDb { + #[cfg(feature = "mongodb")] + return DatabaseInfo::MongoDb { uri: config.database.mongodb, database_name, } .connect() - .await? + .await; + + #[cfg(not(feature = "mongodb"))] + return Err("MongoDB not enabled.".to_string()) } _ => unreachable!("must specify REFERENCE or MONGODB"), } } - DatabaseInfo::Reference => Database::Reference(Default::default()), + DatabaseInfo::Reference => Ok(Database::Reference(Default::default())), + #[cfg(feature = "mongodb")] DatabaseInfo::MongoDb { uri, database_name } => { let client = ::mongodb::Client::with_uri_str(uri) .await .map_err(|_| "Failed to init db connection.".to_string())?; - Database::MongoDb(MongoDb(client, database_name)) + Ok(Database::MongoDb(MongoDb(client, database_name))) } + #[cfg(feature = "mongodb")] DatabaseInfo::MongoDbFromClient(client, database_name) => { - Database::MongoDb(MongoDb(client, database_name)) + Ok(Database::MongoDb(MongoDb(client, database_name))) } - }) + } } } @@ -219,12 +234,16 @@ impl Database { Authifier { database: match self { Database::Reference(_) => Default::default(), + #[cfg(feature = "mongodb")] Database::MongoDb(MongoDb(client, _)) => authifier::Database::MongoDb( authifier::database::MongoDb(client.database("revolt")), ), }, config: auth_config, + #[cfg(feature = "tasks")] event_channel: Some(crate::tasks::authifier_relay::sender()), + #[cfg(not(feature = "tasks"))] + event_channel: None, } } } diff --git a/crates/core/database/src/drivers/mongodb.rs b/crates/core/database/src/drivers/mongodb.rs index e12e60fb..baeddb1d 100644 --- a/crates/core/database/src/drivers/mongodb.rs +++ b/crates/core/database/src/drivers/mongodb.rs @@ -10,7 +10,6 @@ use serde::de::DeserializeOwned; use serde::Serialize; database_derived!( - #[cfg(feature = "mongodb")] /// MongoDB implementation #[derive(Debug)] pub struct MongoDb(pub ::mongodb::Client, pub String); diff --git a/crates/core/database/src/lib.rs b/crates/core/database/src/lib.rs index 8889f196..5c7640da 100644 --- a/crates/core/database/src/lib.rs +++ b/crates/core/database/src/lib.rs @@ -25,6 +25,9 @@ pub use mongodb; #[macro_use] extern crate bson; +#[cfg(not(feature = "async-std-runtime"))] +compile_error!("async-std-runtime feature must be enabled."); + #[macro_export] #[cfg(debug_assertions)] macro_rules! query { @@ -103,6 +106,7 @@ pub mod util; pub use models::*; pub mod events; +#[cfg(feature = "tasks")] pub mod tasks; mod amqp; diff --git a/crates/core/database/src/models/admin_migrations/ops.rs b/crates/core/database/src/models/admin_migrations/ops.rs index ff8ae25d..d49716e4 100644 --- a/crates/core/database/src/models/admin_migrations/ops.rs +++ b/crates/core/database/src/models/admin_migrations/ops.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/bots/ops.rs b/crates/core/database/src/models/bots/ops.rs index 8d77673f..f35a210a 100644 --- a/crates/core/database/src/models/bots/ops.rs +++ b/crates/core/database/src/models/bots/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::{Bot, FieldsBot, PartialBot}; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/channel_invites/ops.rs b/crates/core/database/src/models/channel_invites/ops.rs index 82b2bd8a..59bd7271 100644 --- a/crates/core/database/src/models/channel_invites/ops.rs +++ b/crates/core/database/src/models/channel_invites/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::Invite; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/channel_unreads/ops.rs b/crates/core/database/src/models/channel_unreads/ops.rs index 6c91bf64..70d77d92 100644 --- a/crates/core/database/src/models/channel_unreads/ops.rs +++ b/crates/core/database/src/models/channel_unreads/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::ChannelUnread; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/channel_webhooks/ops.rs b/crates/core/database/src/models/channel_webhooks/ops.rs index d7561a99..4e22ec08 100644 --- a/crates/core/database/src/models/channel_webhooks/ops.rs +++ b/crates/core/database/src/models/channel_webhooks/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::{FieldsWebhook, PartialWebhook, Webhook}; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/channels/model.rs b/crates/core/database/src/models/channels/model.rs index 35d2c833..01647ef3 100644 --- a/crates/core/database/src/models/channels/model.rs +++ b/crates/core/database/src/models/channels/model.rs @@ -9,10 +9,13 @@ use serde::{Deserialize, Serialize}; use ulid::Ulid; use crate::{ - events::client::EventV1, tasks::ack::AckEvent, Database, File, IntoDocumentPath, PartialServer, + events::client::EventV1, Database, File, PartialServer, Server, SystemMessage, User, AMQP, }; +#[cfg(feature = "mongodb")] +use crate::IntoDocumentPath; + auto_derived!( #[serde(tag = "channel_type")] pub enum Channel { @@ -670,10 +673,11 @@ impl Channel { .private(user.to_string()) .await; + #[cfg(feature = "tasks")] crate::tasks::ack::queue_ack( self.id().to_string(), user.to_string(), - AckEvent::AckMessage { + crate::tasks::ack::AckEvent::AckMessage { id: message.to_string(), }, ) @@ -790,6 +794,7 @@ impl Channel { } } +#[cfg(feature = "mongodb")] impl IntoDocumentPath for FieldsChannel { fn as_path(&self) -> Option<&'static str> { Some(match self { diff --git a/crates/core/database/src/models/channels/ops.rs b/crates/core/database/src/models/channels/ops.rs index 2598043e..3ee90d54 100644 --- a/crates/core/database/src/models/channels/ops.rs +++ b/crates/core/database/src/models/channels/ops.rs @@ -1,5 +1,7 @@ use crate::{revolt_result::Result, Channel, FieldsChannel, PartialChannel}; use revolt_permissions::OverrideField; + +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/emojis/ops.rs b/crates/core/database/src/models/emojis/ops.rs index c0b51228..26e23aca 100644 --- a/crates/core/database/src/models/emojis/ops.rs +++ b/crates/core/database/src/models/emojis/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::Emoji; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/file_hashes/ops.rs b/crates/core/database/src/models/file_hashes/ops.rs index 648a1a2f..4b249e4c 100644 --- a/crates/core/database/src/models/file_hashes/ops.rs +++ b/crates/core/database/src/models/file_hashes/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::FileHash; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/files/ops.rs b/crates/core/database/src/models/files/ops.rs index b30d3acc..dd975d52 100644 --- a/crates/core/database/src/models/files/ops.rs +++ b/crates/core/database/src/models/files/ops.rs @@ -4,6 +4,7 @@ use crate::File; use super::FileUsedFor; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/messages/model.rs b/crates/core/database/src/models/messages/model.rs index 33190def..d265c052 100644 --- a/crates/core/database/src/models/messages/model.rs +++ b/crates/core/database/src/models/messages/model.rs @@ -14,7 +14,6 @@ use validator::Validate; use crate::{ events::client::EventV1, - tasks::{self, ack::AckEvent}, util::{ bulk_permissions::BulkDatabasePermissionQuery, idempotency::IdempotencyKey, permissions::DatabasePermissionQuery, @@ -22,6 +21,9 @@ use crate::{ Channel, Database, Emoji, File, User, AMQP, }; +#[cfg(feature = "tasks")] +use crate::tasks::{self, ack::AckEvent}; + auto_derived_partial!( /// Message pub struct Message { @@ -619,9 +621,11 @@ impl Message { .await; // Update last_message_id + #[cfg(feature = "tasks")] tasks::last_message_id::queue(self.channel.to_string(), self.id.to_string(), is_dm).await; // Add mentions for affected users + #[cfg(feature = "tasks")] if !mentions_elsewhere { if let Some(mentions) = &self.mentions { tasks::ack::queue_message( @@ -640,6 +644,7 @@ impl Message { } // Generate embeds + #[cfg(feature = "tasks")] if generate_embeds { if let Some(content) = &self.content { tasks::process_embeds::queue( @@ -676,10 +681,12 @@ impl Message { ) .await?; + if !self.has_suppressed_notifications() && (self.mentions.is_some() || self.contains_mass_push_mention()) { // send Push notifications + #[cfg(feature = "tasks")] tasks::ack::queue_message( self.channel.to_string(), AckEvent::ProcessMessage { diff --git a/crates/core/database/src/models/messages/ops.rs b/crates/core/database/src/models/messages/ops.rs index b10022b4..4d54e83c 100644 --- a/crates/core/database/src/models/messages/ops.rs +++ b/crates/core/database/src/models/messages/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::{AppendMessage, FieldsMessage, Message, MessageQuery, PartialMessage}; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/mod.rs b/crates/core/database/src/models/mod.rs index 181a30c0..93bd556c 100644 --- a/crates/core/database/src/models/mod.rs +++ b/crates/core/database/src/models/mod.rs @@ -38,7 +38,10 @@ pub use servers::*; pub use user_settings::*; pub use users::*; -use crate::{Database, MongoDb, ReferenceDb}; +use crate::{Database, ReferenceDb}; + +#[cfg(feature = "mongodb")] +use crate::MongoDb; pub trait AbstractDatabase: Sync @@ -66,6 +69,8 @@ pub trait AbstractDatabase: } impl AbstractDatabase for ReferenceDb {} + +#[cfg(feature = "mongodb")] impl AbstractDatabase for MongoDb {} impl std::ops::Deref for Database { @@ -74,6 +79,7 @@ impl std::ops::Deref for Database { fn deref(&self) -> &Self::Target { match &self { Database::Reference(dummy) => dummy, + #[cfg(feature = "mongodb")] Database::MongoDb(mongo) => mongo, } } diff --git a/crates/core/database/src/models/policy_changes/ops.rs b/crates/core/database/src/models/policy_changes/ops.rs index 2692a81f..05bc7c2f 100644 --- a/crates/core/database/src/models/policy_changes/ops.rs +++ b/crates/core/database/src/models/policy_changes/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::PolicyChange; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/ratelimit_events/ops.rs b/crates/core/database/src/models/ratelimit_events/ops.rs index 31991da7..53b7dce3 100644 --- a/crates/core/database/src/models/ratelimit_events/ops.rs +++ b/crates/core/database/src/models/ratelimit_events/ops.rs @@ -1,6 +1,8 @@ use std::time::Duration; use crate::{revolt_result::Result, RatelimitEvent, RatelimitEventType}; + +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/safety_reports/ops.rs b/crates/core/database/src/models/safety_reports/ops.rs index ccb8fb5d..7c0712a5 100644 --- a/crates/core/database/src/models/safety_reports/ops.rs +++ b/crates/core/database/src/models/safety_reports/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::Report; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/safety_snapshots/ops.rs b/crates/core/database/src/models/safety_snapshots/ops.rs index 0f9a852b..5a2803d4 100644 --- a/crates/core/database/src/models/safety_snapshots/ops.rs +++ b/crates/core/database/src/models/safety_snapshots/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::Snapshot; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/server_bans/ops.rs b/crates/core/database/src/models/server_bans/ops.rs index 90cb4df3..51bac384 100644 --- a/crates/core/database/src/models/server_bans/ops.rs +++ b/crates/core/database/src/models/server_bans/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::{MemberCompositeKey, ServerBan}; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/server_members/ops.rs b/crates/core/database/src/models/server_members/ops.rs index 1d5a045f..51ddd574 100644 --- a/crates/core/database/src/models/server_members/ops.rs +++ b/crates/core/database/src/models/server_members/ops.rs @@ -1,16 +1,20 @@ -use ::mongodb::SessionCursor; +#[cfg(feature = "mongodb")] +use ::mongodb::{ClientSession, SessionCursor}; + use revolt_result::Result; use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember}; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; #[derive(Debug)] +#[allow(clippy::large_enum_variant)] pub enum ChunkedServerMembersGenerator { #[cfg(feature = "mongodb")] MongoDb { - session: ::mongodb::ClientSession, + session: ClientSession, cursor: Option>, }, @@ -22,7 +26,7 @@ pub enum ChunkedServerMembersGenerator { impl ChunkedServerMembersGenerator { #[cfg(feature = "mongodb")] - pub fn new_mongo(session: ::mongodb::ClientSession, cursor: SessionCursor) -> Self { + pub fn new_mongo(session: ClientSession, cursor: SessionCursor) -> Self { ChunkedServerMembersGenerator::MongoDb { session, cursor: Some(cursor), diff --git a/crates/core/database/src/models/servers/ops.rs b/crates/core/database/src/models/servers/ops.rs index 6c58773a..ee07ba8f 100644 --- a/crates/core/database/src/models/servers/ops.rs +++ b/crates/core/database/src/models/servers/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::{FieldsRole, FieldsServer, PartialRole, PartialServer, Role, Server}; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/user_settings/ops.rs b/crates/core/database/src/models/user_settings/ops.rs index 2dd6bb69..d44b9a41 100644 --- a/crates/core/database/src/models/user_settings/ops.rs +++ b/crates/core/database/src/models/user_settings/ops.rs @@ -2,6 +2,7 @@ use revolt_result::Result; use crate::UserSettings; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/users/ops.rs b/crates/core/database/src/models/users/ops.rs index 356a3f6c..d7586641 100644 --- a/crates/core/database/src/models/users/ops.rs +++ b/crates/core/database/src/models/users/ops.rs @@ -4,6 +4,7 @@ use revolt_result::Result; use crate::{FieldsUser, PartialUser, RelationshipStatus, User}; +#[cfg(feature = "mongodb")] mod mongodb; mod reference; diff --git a/crates/core/database/src/models/users/ops/mongodb.rs b/crates/core/database/src/models/users/ops/mongodb.rs index d4292aeb..66de248e 100644 --- a/crates/core/database/src/models/users/ops/mongodb.rs +++ b/crates/core/database/src/models/users/ops/mongodb.rs @@ -212,16 +212,34 @@ impl AbstractUsers for MongoDb { partial: &PartialUser, remove: Vec, ) -> Result<()> { - query!( - self, - update_one_by_id, - COL, - id, - partial, - remove.iter().map(|x| x as &dyn IntoDocumentPath).collect(), - None - ) - .map(|_| ()) + if remove.contains(&FieldsUser::StatusText) && partial.status.is_some() { + // stupid-ass workaround to fix mongo conflicting the same item + let _: Result<()> = query!( + self, + update_one_by_id, + COL, + id, + PartialUser { + ..Default::default() + }, + remove.iter().map(|x| x as &dyn IntoDocumentPath).collect(), + None + ) + .map(|_| ()); + + query!(self, update_one_by_id, COL, id, partial, vec![], None).map(|_| ()) + } else { + query!( + self, + update_one_by_id, + COL, + id, + partial, + remove.iter().map(|x| x as &dyn IntoDocumentPath).collect(), + None + ) + .map(|_| ()) + } } /// Set relationship with another user diff --git a/crates/core/database/src/util/reference.rs b/crates/core/database/src/util/reference.rs index 9282d39d..a0aefc40 100644 --- a/crates/core/database/src/util/reference.rs +++ b/crates/core/database/src/util/reference.rs @@ -14,41 +14,40 @@ use crate::{ }; /// Reference to some object in the database -#[derive(Serialize, Deserialize)] -pub struct Reference { +pub struct Reference<'a> { /// Id of object - pub id: String, + pub id: &'a str, } -impl Reference { +impl<'a> Reference<'a> { /// Create a Ref from an unchecked string - pub fn from_unchecked(id: String) -> Reference { + pub fn from_unchecked(id: &'a str) -> Reference<'a> { Reference { id } } /// Fetch ban from Ref pub async fn as_ban(&self, db: &Database, server: &str) -> Result { - db.fetch_ban(server, &self.id).await + db.fetch_ban(server, self.id).await } /// Fetch bot from Ref pub async fn as_bot(&self, db: &Database) -> Result { - db.fetch_bot(&self.id).await + db.fetch_bot(self.id).await } /// Fetch emoji from Ref pub async fn as_emoji(&self, db: &Database) -> Result { - db.fetch_emoji(&self.id).await + db.fetch_emoji(self.id).await } /// Fetch channel from Ref pub async fn as_channel(&self, db: &Database) -> Result { - db.fetch_channel(&self.id).await + db.fetch_channel(self.id).await } /// Fetch invite from Ref or create invite to server if discoverable pub async fn as_invite(&self, db: &Database) -> Result { - if ulid::Ulid::from_str(&self.id).is_ok() { + if ulid::Ulid::from_str(self.id).is_ok() { let server = self.as_server(db).await?; if !server.discoverable { return Err(create_error!(NotFound)); @@ -65,18 +64,18 @@ impl Reference { .ok_or(create_error!(NotFound))?, }) } else { - db.fetch_invite(&self.id).await + db.fetch_invite(self.id).await } } /// Fetch message from Ref pub async fn as_message(&self, db: &Database) -> Result { - db.fetch_message(&self.id).await + db.fetch_message(self.id).await } /// Fetch message from Ref and validate channel pub async fn as_message_in_channel(&self, db: &Database, channel: &str) -> Result { - let msg = db.fetch_message(&self.id).await?; + let msg = db.fetch_message(self.id).await?; if msg.channel != channel { return Err(create_error!(NotFound)); } @@ -86,36 +85,36 @@ impl Reference { /// Fetch member from Ref pub async fn as_member(&self, db: &Database, server: &str) -> Result { - db.fetch_member(server, &self.id).await + db.fetch_member(server, self.id).await } /// Fetch server from Ref pub async fn as_server(&self, db: &Database) -> Result { - db.fetch_server(&self.id).await + db.fetch_server(self.id).await } /// Fetch user from Ref pub async fn as_user(&self, db: &Database) -> Result { - db.fetch_user(&self.id).await + db.fetch_user(self.id).await } /// Fetch webhook from Ref pub async fn as_webhook(&self, db: &Database) -> Result { - db.fetch_webhook(&self.id).await + db.fetch_webhook(self.id).await } } #[cfg(feature = "rocket-impl")] -impl<'r> FromParam<'r> for Reference { +impl<'r> FromParam<'r> for Reference<'r> { type Error = &'r str; fn from_param(param: &'r str) -> Result { - Ok(Reference::from_unchecked(param.into())) + Ok(Reference::from_unchecked(param)) } } #[cfg(feature = "rocket-impl")] -impl JsonSchema for Reference { +impl<'a> JsonSchema for Reference<'a> { fn schema_name() -> String { "Id".to_string() } diff --git a/crates/core/database/src/voice/mod.rs b/crates/core/database/src/voice/mod.rs index 37a42dc4..def56db1 100644 --- a/crates/core/database/src/voice/mod.rs +++ b/crates/core/database/src/voice/mod.rs @@ -362,7 +362,7 @@ pub async fn sync_voice_permissions( .iter() .flatten() { - let user = Reference::from_unchecked(user_id.clone()) + let user = Reference::from_unchecked(&user_id) .as_user(db) .await?; @@ -387,7 +387,7 @@ pub async fn sync_user_voice_permissions( let member = match server_id { Some(server_id) => Some( - Reference::from_unchecked(user.id.clone()) + Reference::from_unchecked(&user.id) .as_member(db, server_id) .await?, ), diff --git a/crates/core/models/src/v0/bots.rs b/crates/core/models/src/v0/bots.rs index 0e58bd15..70c66c46 100644 --- a/crates/core/models/src/v0/bots.rs +++ b/crates/core/models/src/v0/bots.rs @@ -132,8 +132,8 @@ auto_derived!( #[cfg_attr(feature = "validator", validate(length(min = 1, max = 2048)))] pub interactions_url: Option, /// Fields to remove from bot object - #[cfg_attr(feature = "validator", validate(length(min = 1)))] - pub remove: Option>, + #[cfg_attr(feature = "serde", serde(default))] + pub remove: Vec, } /// Where we are inviting a bot to diff --git a/crates/core/models/src/v0/channels.rs b/crates/core/models/src/v0/channels.rs index 630bfde5..4c6ddcf0 100644 --- a/crates/core/models/src/v0/channels.rs +++ b/crates/core/models/src/v0/channels.rs @@ -227,7 +227,7 @@ auto_derived!( /// Fields to remove from channel #[cfg_attr(feature = "serde", serde(default))] - pub remove: Option>, + pub remove: Vec, } /// Create new group diff --git a/crates/core/models/src/v0/messages.rs b/crates/core/models/src/v0/messages.rs index 78d9cbc6..67af69f8 100644 --- a/crates/core/models/src/v0/messages.rs +++ b/crates/core/models/src/v0/messages.rs @@ -217,7 +217,7 @@ auto_derived!( #[derive(Default)] #[cfg_attr(feature = "validator", derive(Validate))] pub struct SendableEmbed { - #[cfg_attr(feature = "validator", validate(length(min = 1, max = 128)))] + #[cfg_attr(feature = "validator", validate(length(min = 1, max = 256)))] pub icon_url: Option, #[cfg_attr(feature = "validator", validate(length(min = 1, max = 256)))] pub url: Option, diff --git a/crates/core/models/src/v0/server_members.rs b/crates/core/models/src/v0/server_members.rs index d1cbe965..de49bebb 100644 --- a/crates/core/models/src/v0/server_members.rs +++ b/crates/core/models/src/v0/server_members.rs @@ -140,8 +140,7 @@ auto_derived!( /// voice channel to move to if already in a voice channel pub voice_channel: Option, /// Fields to remove from channel object - #[cfg_attr(feature = "validator", validate(length(min = 1)))] - pub remove: Option>, - + #[cfg_attr(feature = "serde", serde(default))] + pub remove: Vec, } ); diff --git a/crates/core/models/src/v0/servers.rs b/crates/core/models/src/v0/servers.rs index 4c7e1ee8..c3ed20a8 100644 --- a/crates/core/models/src/v0/servers.rs +++ b/crates/core/models/src/v0/servers.rs @@ -175,6 +175,8 @@ auto_derived!( /// Ranking position /// /// Smaller values take priority. + /// + /// **Removed** - no effect, use the edit server role positions route pub rank: Option, } @@ -247,8 +249,8 @@ auto_derived!( pub analytics: Option, /// Fields to remove from server object - #[cfg_attr(feature = "validator", validate(length(min = 1)))] - pub remove: Option>, + #[cfg_attr(feature = "serde", serde(default))] + pub remove: Vec, } /// New role information @@ -270,8 +272,8 @@ auto_derived!( /// **Removed** - no effect, use the edit server role positions route pub rank: Option, /// Fields to remove from role object - #[cfg_attr(feature = "validator", validate(length(min = 1)))] - pub remove: Option>, + #[cfg_attr(feature = "serde", serde(default))] + pub remove: Vec, } /// New role permissions diff --git a/crates/core/models/src/v0/users.rs b/crates/core/models/src/v0/users.rs index d5e65673..3fd6e255 100644 --- a/crates/core/models/src/v0/users.rs +++ b/crates/core/models/src/v0/users.rs @@ -245,8 +245,8 @@ auto_derived!( pub flags: Option, /// Fields to remove from user object - #[cfg_attr(feature = "validator", validate(length(min = 1)))] - pub remove: Option>, + #[cfg_attr(feature = "serde", serde(default))] + pub remove: Vec, } /// User flag reponse diff --git a/crates/daemons/pushd/Cargo.toml b/crates/daemons/pushd/Cargo.toml index 50db680b..40a28008 100644 --- a/crates/daemons/pushd/Cargo.toml +++ b/crates/daemons/pushd/Cargo.toml @@ -8,6 +8,7 @@ license = "AGPL-3.0-or-later" revolt-result = { version = "0.8.8", path = "../../core/result" } revolt-config = { version = "0.8.8", path = "../../core/config", features = [ "report-macros", + "anyhow" ] } revolt-database = { version = "0.8.8", path = "../../core/database" } revolt-models = { version = "0.8.8", path = "../../core/models", features = [ diff --git a/crates/daemons/voice-ingress/src/api.rs b/crates/daemons/voice-ingress/src/api.rs index 086ea573..a8e1e0fe 100644 --- a/crates/daemons/voice-ingress/src/api.rs +++ b/crates/daemons/voice-ingress/src/api.rs @@ -59,7 +59,7 @@ pub async fn ingress( let channel_id = channel_id.to_internal_error()?; let user_id = user_id.to_internal_error()?; - let channel = Reference::from_unchecked(channel_id.clone()) + let channel = Reference::from_unchecked(&channel_id) .as_channel(db) .await?; @@ -68,30 +68,30 @@ pub async fn ingress( // Only publish one event when a user is moved from one channel to another. if let Some(moved_from) = get_user_moved_to_voice(channel_id, user_id).await? { EventV1::VoiceChannelMove { - user: user_id.clone(), + user: user_id.to_string(), from: moved_from, - to: channel_id.clone(), + to: channel_id.to_string(), state: voice_state, } - .p(channel_id.clone()) + .p(channel_id.to_string()) .await; } else { EventV1::VoiceChannelJoin { - id: channel_id.clone(), + id: channel_id.to_string(), state: voice_state, } - .p(channel_id.clone()) + .p(channel_id.to_string()) .await; }; // First user who joined - send call started system message. if event.room.as_ref().unwrap().num_participants == 1 { - let user = Reference::from_unchecked(user_id.clone()) + let user = Reference::from_unchecked(&user_id) .as_user(db) .await?; let mut call_started_message = SystemMessage::CallStarted { - by: user_id.clone(), + by: user_id.to_string(), finished_at: None, } .into_message(channel.id().to_string()); @@ -120,7 +120,7 @@ pub async fn ingress( let channel_id = channel_id.to_internal_error()?; let user_id = user_id.to_internal_error()?; - let channel = Reference::from_unchecked(channel_id.clone()) + let channel = Reference::from_unchecked(&channel_id) .as_channel(db) .await?; @@ -147,7 +147,7 @@ pub async fn ingress( take_channel_call_started_system_message(channel_id).await? { // Could have been deleted - if let Ok(mut message) = Reference::from_unchecked(system_message_id) + if let Ok(mut message) = Reference::from_unchecked(&system_message_id) .as_message(db) .await { @@ -179,11 +179,11 @@ pub async fn ingress( let user_id = user_id.to_internal_error()?; let track = event.track.as_ref().to_internal_error()?; - let channel = Reference::from_unchecked(channel_id.clone()) + let channel = Reference::from_unchecked(&channel_id) .as_channel(db) .await?; - let user = Reference::from_unchecked(user_id.clone()) + let user = Reference::from_unchecked(&user_id) .as_user(db) .await?; diff --git a/crates/delta/src/routes/bots/delete.rs b/crates/delta/src/routes/bots/delete.rs index 7785a544..4d4daefb 100644 --- a/crates/delta/src/routes/bots/delete.rs +++ b/crates/delta/src/routes/bots/delete.rs @@ -11,7 +11,7 @@ use rocket_empty::EmptyResponse; pub async fn delete_bot( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result { let bot = target.as_bot(db).await?; if bot.owner != user.id { diff --git a/crates/delta/src/routes/bots/edit.rs b/crates/delta/src/routes/bots/edit.rs index e90b4bef..6c454e13 100644 --- a/crates/delta/src/routes/bots/edit.rs +++ b/crates/delta/src/routes/bots/edit.rs @@ -14,7 +14,7 @@ use validator::Validate; pub async fn edit_bot( db: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -37,7 +37,7 @@ pub async fn edit_bot( if data.public.is_none() && data.analytics.is_none() && data.interactions_url.is_none() - && data.remove.is_none() + && data.remove.is_empty() { return Ok(Json(v0::BotWithUserResponse { bot: bot.into(), @@ -64,7 +64,6 @@ pub async fn edit_bot( db, partial, remove - .unwrap_or_default() .into_iter() .map(|v| v.into()) .collect(), @@ -100,7 +99,7 @@ mod test { .body( json!(v0::DataEditBot { public: Some(true), - remove: Some(vec![FieldsBot::Token]), + remove: vec![FieldsBot::Token], ..Default::default() }) .to_string(), diff --git a/crates/delta/src/routes/bots/fetch.rs b/crates/delta/src/routes/bots/fetch.rs index a5222b8f..586ce124 100644 --- a/crates/delta/src/routes/bots/fetch.rs +++ b/crates/delta/src/routes/bots/fetch.rs @@ -11,7 +11,7 @@ use rocket::{serde::json::Json, State}; pub async fn fetch_bot( db: &State, user: User, - bot: Reference, + bot: Reference<'_>, ) -> Result> { if user.bot.is_some() { return Err(create_error!(IsBot)); diff --git a/crates/delta/src/routes/bots/fetch_public.rs b/crates/delta/src/routes/bots/fetch_public.rs index 6fa4f792..7ad97e00 100644 --- a/crates/delta/src/routes/bots/fetch_public.rs +++ b/crates/delta/src/routes/bots/fetch_public.rs @@ -13,9 +13,9 @@ use rocket::State; pub async fn fetch_public_bot( db: &State, user: Option, - target: Reference, + target: Reference<'_>, ) -> Result> { - let bot = db.fetch_bot(&target.id).await?; + let bot = db.fetch_bot(target.id).await?; if !bot.public && user.is_none_or(|x| x.id != bot.owner) { return Err(create_error!(NotFound)); } diff --git a/crates/delta/src/routes/bots/invite.rs b/crates/delta/src/routes/bots/invite.rs index 10c09eed..39517c51 100644 --- a/crates/delta/src/routes/bots/invite.rs +++ b/crates/delta/src/routes/bots/invite.rs @@ -20,7 +20,7 @@ pub async fn invite_bot( db: &State, amqp: &State, user: User, - target: Reference, + target: Reference<'_>, dest: Json, ) -> Result { if user.bot.is_some() { diff --git a/crates/delta/src/routes/channels/channel_ack.rs b/crates/delta/src/routes/channels/channel_ack.rs index 458ccd1b..2ae0d3b0 100644 --- a/crates/delta/src/routes/channels/channel_ack.rs +++ b/crates/delta/src/routes/channels/channel_ack.rs @@ -15,8 +15,8 @@ use rocket_empty::EmptyResponse; pub async fn ack( db: &State, user: User, - target: Reference, - message: Reference, + target: Reference<'_>, + message: Reference<'_>, ) -> Result { if user.bot.is_some() { return Err(create_error!(IsBot)); @@ -29,7 +29,7 @@ pub async fn ack( .throw_if_lacking_channel_permission(ChannelPermission::ViewChannel)?; channel - .ack(&user.id, &message.id) + .ack(&user.id, message.id) .await .map(|_| EmptyResponse) } diff --git a/crates/delta/src/routes/channels/channel_delete.rs b/crates/delta/src/routes/channels/channel_delete.rs index 4d6c3cdc..1282f658 100644 --- a/crates/delta/src/routes/channels/channel_delete.rs +++ b/crates/delta/src/routes/channels/channel_delete.rs @@ -17,7 +17,7 @@ pub async fn delete( voice_client: &State, amqp: &State, user: User, - target: Reference, + target: Reference<'_>, options: v0::OptionsChannelDelete, ) -> Result { let mut channel = target.as_channel(db).await?; diff --git a/crates/delta/src/routes/channels/channel_edit.rs b/crates/delta/src/routes/channels/channel_edit.rs index b74c176c..355fa246 100644 --- a/crates/delta/src/routes/channels/channel_edit.rs +++ b/crates/delta/src/routes/channels/channel_edit.rs @@ -17,7 +17,7 @@ pub async fn edit( db: &State, amqp: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -39,7 +39,7 @@ pub async fn edit( && data.nsfw.is_none() && data.owner.is_none() && data.voice.is_none() - && data.remove.is_none() + && data.remove.is_empty() { return Ok(Json(channel.into())); } @@ -97,23 +97,21 @@ pub async fn edit( nsfw, .. } => { - if let Some(fields) = &data.remove { - if fields.contains(&v0::FieldsChannel::Icon) { - if let Some(icon) = &icon { - db.mark_attachment_as_deleted(&icon.id).await?; - } + if data.remove.contains(&v0::FieldsChannel::Icon) { + if let Some(icon) = &icon { + db.mark_attachment_as_deleted(&icon.id).await?; } + } - for field in fields { - match field { - v0::FieldsChannel::Description => { - description.take(); - } - v0::FieldsChannel::Icon => { - icon.take(); - } - _ => {} + for field in &data.remove { + match field { + v0::FieldsChannel::Description => { + description.take(); } + v0::FieldsChannel::Icon => { + icon.take(); + } + _ => {} } } @@ -202,23 +200,21 @@ pub async fn edit( voice, .. } => { - if let Some(fields) = &data.remove { - if fields.contains(&v0::FieldsChannel::Icon) { - if let Some(icon) = &icon { - db.mark_attachment_as_deleted(&icon.id).await?; - } + if data.remove.contains(&v0::FieldsChannel::Icon) { + if let Some(icon) = &icon { + db.mark_attachment_as_deleted(&icon.id).await?; } + } - for field in fields { - match field { - v0::FieldsChannel::Description => { - description.take(); - } - v0::FieldsChannel::Icon => { - icon.take(); - } - _ => {} + for field in &data.remove { + match field { + v0::FieldsChannel::Description => { + description.take(); } + v0::FieldsChannel::Icon => { + icon.take(); + } + _ => {} } } @@ -255,7 +251,6 @@ pub async fn edit( db, partial, data.remove - .unwrap_or_default() .into_iter() .map(|f| f.into()) .collect(), diff --git a/crates/delta/src/routes/channels/channel_fetch.rs b/crates/delta/src/routes/channels/channel_fetch.rs index dfcc918d..b08239bb 100644 --- a/crates/delta/src/routes/channels/channel_fetch.rs +++ b/crates/delta/src/routes/channels/channel_fetch.rs @@ -16,7 +16,7 @@ use rocket::{serde::json::Json, State}; pub async fn fetch( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { let channel = target.as_channel(db).await?; diff --git a/crates/delta/src/routes/channels/group_add_member.rs b/crates/delta/src/routes/channels/group_add_member.rs index 79d9e633..ac1aa886 100644 --- a/crates/delta/src/routes/channels/group_add_member.rs +++ b/crates/delta/src/routes/channels/group_add_member.rs @@ -17,8 +17,8 @@ pub async fn add_member( db: &State, amqp: &State, user: User, - group_id: Reference, - member_id: Reference, + group_id: Reference<'_>, + member_id: Reference<'_>, ) -> Result { if user.bot.is_some() { return Err(create_error!(IsBot)); diff --git a/crates/delta/src/routes/channels/group_remove_member.rs b/crates/delta/src/routes/channels/group_remove_member.rs index 049762eb..21e71714 100644 --- a/crates/delta/src/routes/channels/group_remove_member.rs +++ b/crates/delta/src/routes/channels/group_remove_member.rs @@ -15,8 +15,8 @@ pub async fn remove_member( voice_client: &State, amqp: &State, user: User, - target: Reference, - member: Reference, + target: Reference<'_>, + member: Reference<'_>, ) -> Result { if user.bot.is_some() { return Err(create_error!(IsBot)); diff --git a/crates/delta/src/routes/channels/invite_create.rs b/crates/delta/src/routes/channels/invite_create.rs index 1214816e..104f3398 100644 --- a/crates/delta/src/routes/channels/invite_create.rs +++ b/crates/delta/src/routes/channels/invite_create.rs @@ -18,7 +18,7 @@ use rocket::{serde::json::Json, State}; pub async fn create_invite( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { if user.bot.is_some() { return Err(create_error!(IsBot)); diff --git a/crates/delta/src/routes/channels/members_fetch.rs b/crates/delta/src/routes/channels/members_fetch.rs index 4a6688bf..dc681519 100644 --- a/crates/delta/src/routes/channels/members_fetch.rs +++ b/crates/delta/src/routes/channels/members_fetch.rs @@ -17,7 +17,7 @@ use rocket::{serde::json::Json, State}; pub async fn fetch_members( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result>> { let channel = target.as_channel(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).channel(&channel); diff --git a/crates/delta/src/routes/channels/message_bulk_delete.rs b/crates/delta/src/routes/channels/message_bulk_delete.rs index 446b1e26..fdd538ff 100644 --- a/crates/delta/src/routes/channels/message_bulk_delete.rs +++ b/crates/delta/src/routes/channels/message_bulk_delete.rs @@ -22,7 +22,7 @@ use validator::Validate; pub async fn bulk_delete_messages( db: &State, user: User, - target: Reference, + target: Reference<'_>, options: Json, ) -> Result { let options = options.into_inner(); @@ -51,7 +51,7 @@ pub async fn bulk_delete_messages( .await .throw_if_lacking_channel_permission(ChannelPermission::ManageMessages)?; - Message::bulk_delete(db, &target.id, options.ids) + Message::bulk_delete(db, target.id, options.ids) .await .map(|_| EmptyResponse) } diff --git a/crates/delta/src/routes/channels/message_clear_reactions.rs b/crates/delta/src/routes/channels/message_clear_reactions.rs index 268bc843..cf9be252 100644 --- a/crates/delta/src/routes/channels/message_clear_reactions.rs +++ b/crates/delta/src/routes/channels/message_clear_reactions.rs @@ -17,8 +17,8 @@ use rocket_empty::EmptyResponse; pub async fn clear_reactions( db: &State, user: User, - target: Reference, - msg: Reference, + target: Reference<'_>, + msg: Reference<'_>, ) -> Result { let channel = target.as_channel(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).channel(&channel); diff --git a/crates/delta/src/routes/channels/message_delete.rs b/crates/delta/src/routes/channels/message_delete.rs index 3c1f1e7e..437c80ee 100644 --- a/crates/delta/src/routes/channels/message_delete.rs +++ b/crates/delta/src/routes/channels/message_delete.rs @@ -15,10 +15,10 @@ use rocket_empty::EmptyResponse; pub async fn delete( db: &State, user: User, - target: Reference, - msg: Reference, + target: Reference<'_>, + msg: Reference<'_>, ) -> Result { - let message = msg.as_message_in_channel(db, &target.id).await?; + let message = msg.as_message_in_channel(db, target.id).await?; if message.author != user.id { let channel = target.as_channel(db).await?; diff --git a/crates/delta/src/routes/channels/message_edit.rs b/crates/delta/src/routes/channels/message_edit.rs index 2b5d24f7..53426ec0 100644 --- a/crates/delta/src/routes/channels/message_edit.rs +++ b/crates/delta/src/routes/channels/message_edit.rs @@ -18,8 +18,8 @@ use validator::Validate; pub async fn edit( db: &State, user: User, - target: Reference, - msg: Reference, + target: Reference<'_>, + msg: Reference<'_>, edit: Json, ) -> Result> { let edit = edit.into_inner(); diff --git a/crates/delta/src/routes/channels/message_fetch.rs b/crates/delta/src/routes/channels/message_fetch.rs index b5e89685..8f09d47f 100644 --- a/crates/delta/src/routes/channels/message_fetch.rs +++ b/crates/delta/src/routes/channels/message_fetch.rs @@ -15,8 +15,8 @@ use rocket::{serde::json::Json, State}; pub async fn fetch( db: &State, user: User, - target: Reference, - msg: Reference, + target: Reference<'_>, + msg: Reference<'_>, ) -> Result> { let channel = target.as_channel(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).channel(&channel); diff --git a/crates/delta/src/routes/channels/message_pin.rs b/crates/delta/src/routes/channels/message_pin.rs index 8078d35b..bcc97341 100644 --- a/crates/delta/src/routes/channels/message_pin.rs +++ b/crates/delta/src/routes/channels/message_pin.rs @@ -1,4 +1,7 @@ -use revolt_database::{util::{permissions::DatabasePermissionQuery, reference::Reference}, Channel, Database, PartialMessage, SystemMessage, User, AMQP}; +use revolt_database::{ + util::{permissions::DatabasePermissionQuery, reference::Reference}, + Channel, Database, PartialMessage, SystemMessage, User, AMQP, +}; use revolt_models::v0::MessageAuthor; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; @@ -14,8 +17,8 @@ pub async fn message_pin( db: &State, amqp: &State, user: User, - target: Reference, - msg: Reference, + target: Reference<'_>, + msg: Reference<'_>, ) -> Result { let channel = target.as_channel(db).await?; @@ -169,7 +172,7 @@ mod test { }) .await; - let updated_message = Reference::from_unchecked(message.id) + let updated_message = Reference::from_unchecked(&message.id) .as_message(&harness.db) .await .expect("Failed to find updated message"); diff --git a/crates/delta/src/routes/channels/message_query.rs b/crates/delta/src/routes/channels/message_query.rs index 2ab6e8da..19b1d401 100644 --- a/crates/delta/src/routes/channels/message_query.rs +++ b/crates/delta/src/routes/channels/message_query.rs @@ -16,7 +16,7 @@ use validator::Validate; pub async fn query( db: &State, user: User, - target: Reference, + target: Reference<'_>, options: v0::OptionsQueryMessages, ) -> Result> { options.validate().map_err(|error| { diff --git a/crates/delta/src/routes/channels/message_react.rs b/crates/delta/src/routes/channels/message_react.rs index 5acb00f6..6d3edb2a 100644 --- a/crates/delta/src/routes/channels/message_react.rs +++ b/crates/delta/src/routes/channels/message_react.rs @@ -15,9 +15,9 @@ use rocket_empty::EmptyResponse; pub async fn react_message( db: &State, user: User, - target: Reference, - msg: Reference, - emoji: Reference, + target: Reference<'_>, + msg: Reference<'_>, + emoji: Reference<'_>, ) -> Result { let channel = target.as_channel(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).channel(&channel); @@ -30,7 +30,7 @@ pub async fn react_message( // Add the reaction message - .add_reaction(db, &user, &emoji.id) + .add_reaction(db, &user, emoji.id) .await .map(|_| EmptyResponse) } diff --git a/crates/delta/src/routes/channels/message_search.rs b/crates/delta/src/routes/channels/message_search.rs index b3b90071..6adb1837 100644 --- a/crates/delta/src/routes/channels/message_search.rs +++ b/crates/delta/src/routes/channels/message_search.rs @@ -16,7 +16,7 @@ use validator::Validate; pub async fn search( db: &State, user: User, - target: Reference, + target: Reference<'_>, options: Json, ) -> Result> { if user.bot.is_some() { diff --git a/crates/delta/src/routes/channels/message_send.rs b/crates/delta/src/routes/channels/message_send.rs index 0db142bb..e0dac276 100644 --- a/crates/delta/src/routes/channels/message_send.rs +++ b/crates/delta/src/routes/channels/message_send.rs @@ -21,7 +21,7 @@ pub async fn message_send( db: &State, amqp: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, idempotency: IdempotencyKey, ) -> Result> { @@ -204,7 +204,7 @@ mod test { Member::create(&harness.db, &server, &user, Some(channels.clone())) .await .expect("Failed to create member"); - let member = Reference::from_unchecked(user.id.clone()) + let member = Reference::from_unchecked(&user.id) .as_member(&harness.db, &server.id) .await .expect("Failed to get member"); @@ -244,7 +244,7 @@ mod test { Member::create(&harness.db, &server, &second_user, Some(channels.clone())) .await .expect("Failed to create second member"); - let mut second_member = Reference::from_unchecked(second_user.id.clone()) + let mut second_member = Reference::from_unchecked(&second_user.id) .as_member(&harness.db, &server.id) .await .expect("Failed to get second member"); diff --git a/crates/delta/src/routes/channels/message_unpin.rs b/crates/delta/src/routes/channels/message_unpin.rs index 7fe5fba9..3770606d 100644 --- a/crates/delta/src/routes/channels/message_unpin.rs +++ b/crates/delta/src/routes/channels/message_unpin.rs @@ -14,8 +14,8 @@ pub async fn message_unpin( db: &State, amqp: &State, user: User, - target: Reference, - msg: Reference, + target: Reference<'_>, + msg: Reference<'_>, ) -> Result { let channel = target.as_channel(db).await?; @@ -91,7 +91,7 @@ mod test { Member::create(&harness.db, &server, &user, Some(channels.clone())) .await .expect("Failed to create member"); - let member = Reference::from_unchecked(user.id.clone()) + let member = Reference::from_unchecked(&user.id) .as_member(&harness.db, &server.id) .await .expect("Failed to get member"); @@ -174,7 +174,7 @@ mod test { }) .await; - let updated_message = Reference::from_unchecked(message.id) + let updated_message = Reference::from_unchecked(&message.id) .as_message(&harness.db) .await .expect("Failed to find updated message"); diff --git a/crates/delta/src/routes/channels/message_unreact.rs b/crates/delta/src/routes/channels/message_unreact.rs index d1692d7b..285a1c43 100644 --- a/crates/delta/src/routes/channels/message_unreact.rs +++ b/crates/delta/src/routes/channels/message_unreact.rs @@ -18,9 +18,9 @@ use rocket_empty::EmptyResponse; pub async fn unreact_message( db: &State, user: User, - target: Reference, - msg: Reference, - emoji: Reference, + target: Reference<'_>, + msg: Reference<'_>, + emoji: Reference<'_>, options: v0::OptionsUnreact, ) -> Result { let channel = target.as_channel(db).await?; @@ -41,14 +41,14 @@ pub async fn unreact_message( // Check if we should wipe all of this reaction if remove_all { return message - .clear_reaction(db, &emoji.id) + .clear_reaction(db, emoji.id) .await .map(|_| EmptyResponse); } // Remove the reaction message - .remove_reaction(db, options.user_id.as_ref().unwrap_or(&user.id), &emoji.id) + .remove_reaction(db, options.user_id.as_ref().unwrap_or(&user.id), emoji.id) .await .map(|_| EmptyResponse) } diff --git a/crates/delta/src/routes/channels/mod.rs b/crates/delta/src/routes/channels/mod.rs index 10c83dc4..c57fbaa8 100644 --- a/crates/delta/src/routes/channels/mod.rs +++ b/crates/delta/src/routes/channels/mod.rs @@ -50,7 +50,7 @@ pub fn routes() -> (Vec, OpenApi) { group_remove_member::remove_member, voice_join::call, permissions_set::set_role_permissions, - permissions_set_default::set_default_permissions, + permissions_set_default::set_default_channel_permissions, message_react::react_message, message_unreact::unreact_message, message_clear_reactions::clear_reactions, diff --git a/crates/delta/src/routes/channels/permissions_set.rs b/crates/delta/src/routes/channels/permissions_set.rs index d5ba55cf..88f5f34f 100644 --- a/crates/delta/src/routes/channels/permissions_set.rs +++ b/crates/delta/src/routes/channels/permissions_set.rs @@ -17,7 +17,7 @@ pub async fn set_role_permissions( db: &State, voice_client: &State, user: User, - target: Reference, + target: Reference<'_>, role_id: String, data: Json, ) -> Result> { diff --git a/crates/delta/src/routes/channels/permissions_set_default.rs b/crates/delta/src/routes/channels/permissions_set_default.rs index 14386281..3cfcf1a0 100644 --- a/crates/delta/src/routes/channels/permissions_set_default.rs +++ b/crates/delta/src/routes/channels/permissions_set_default.rs @@ -13,11 +13,11 @@ use rocket::{serde::json::Json, State}; /// Channel must be a `Group`, `TextChannel` or `VoiceChannel`. #[openapi(tag = "Channel Permissions")] #[put("//permissions/default", data = "", rank = 1)] -pub async fn set_default_permissions( +pub async fn set_default_channel_permissions( db: &State, voice_client: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -72,7 +72,7 @@ pub async fn set_default_permissions( } let server = match channel.server() { - Some(server_id) => Some(Reference::from_unchecked(server_id.to_string()).as_server(db).await?), + Some(server_id) => Some(Reference::from_unchecked(server_id).as_server(db).await?), None => None }; diff --git a/crates/delta/src/routes/channels/voice_join.rs b/crates/delta/src/routes/channels/voice_join.rs index c7c041a9..8b6ae389 100644 --- a/crates/delta/src/routes/channels/voice_join.rs +++ b/crates/delta/src/routes/channels/voice_join.rs @@ -22,7 +22,7 @@ pub async fn call( db: &State, voice_client: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { if !voice_client.is_enabled() { @@ -79,7 +79,7 @@ pub async fn call( for channel_id in get_user_voice_channels(&user.id).await? { let node = get_channel_node(&channel_id).await?.unwrap(); - let channel = Reference::from_unchecked(channel_id.clone()) + let channel = Reference::from_unchecked(&channel_id) .as_channel(db) .await?; diff --git a/crates/delta/src/routes/channels/webhook_create.rs b/crates/delta/src/routes/channels/webhook_create.rs index f17c64ff..71f8e8de 100644 --- a/crates/delta/src/routes/channels/webhook_create.rs +++ b/crates/delta/src/routes/channels/webhook_create.rs @@ -19,7 +19,7 @@ use validator::Validate; pub async fn create_webhook( db: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); diff --git a/crates/delta/src/routes/channels/webhook_fetch_all.rs b/crates/delta/src/routes/channels/webhook_fetch_all.rs index 6afc7ac8..4c4fdfd8 100644 --- a/crates/delta/src/routes/channels/webhook_fetch_all.rs +++ b/crates/delta/src/routes/channels/webhook_fetch_all.rs @@ -15,7 +15,7 @@ use rocket::{serde::json::Json, State}; pub async fn fetch_webhooks( db: &State, user: User, - channel_id: Reference, + channel_id: Reference<'_>, ) -> Result>> { let channel = channel_id.as_channel(db).await?; diff --git a/crates/delta/src/routes/customisation/emoji_delete.rs b/crates/delta/src/routes/customisation/emoji_delete.rs index 05d89eb0..155d730d 100644 --- a/crates/delta/src/routes/customisation/emoji_delete.rs +++ b/crates/delta/src/routes/customisation/emoji_delete.rs @@ -16,7 +16,7 @@ use rocket_empty::EmptyResponse; pub async fn delete_emoji( db: &State, user: User, - emoji_id: Reference, + emoji_id: Reference<'_>, ) -> Result { // Fetch the emoji let emoji = emoji_id.as_emoji(db).await?; @@ -26,7 +26,7 @@ pub async fn delete_emoji( // Otherwise, validate we have permission to delete from parent match &emoji.parent { EmojiParent::Server { id } => { - let server = db.fetch_server(id).await?; + let server = db.fetch_server(id.as_str()).await?; // Check for permission let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/customisation/emoji_fetch.rs b/crates/delta/src/routes/customisation/emoji_fetch.rs index 375ebe59..cdc9aaed 100644 --- a/crates/delta/src/routes/customisation/emoji_fetch.rs +++ b/crates/delta/src/routes/customisation/emoji_fetch.rs @@ -9,7 +9,7 @@ use rocket::{serde::json::Json, State}; /// Fetch an emoji by its id. #[openapi(tag = "Emojis")] #[get("/emoji/")] -pub async fn fetch_emoji(db: &State, emoji_id: Reference) -> Result> { +pub async fn fetch_emoji(db: &State, emoji_id: Reference<'_>) -> Result> { emoji_id .as_emoji(db) .await diff --git a/crates/delta/src/routes/invites/invite_delete.rs b/crates/delta/src/routes/invites/invite_delete.rs index a13c3953..cbdc5db5 100644 --- a/crates/delta/src/routes/invites/invite_delete.rs +++ b/crates/delta/src/routes/invites/invite_delete.rs @@ -12,7 +12,7 @@ use rocket_empty::EmptyResponse; /// Delete an invite by its id. #[openapi(tag = "Invites")] #[delete("/")] -pub async fn delete(db: &State, user: User, target: Reference) -> Result { +pub async fn delete(db: &State, user: User, target: Reference<'_>) -> Result { let invite = target.as_invite(db).await?; if user.id == invite.creator() { diff --git a/crates/delta/src/routes/invites/invite_fetch.rs b/crates/delta/src/routes/invites/invite_fetch.rs index 641741b9..7c1b7550 100644 --- a/crates/delta/src/routes/invites/invite_fetch.rs +++ b/crates/delta/src/routes/invites/invite_fetch.rs @@ -8,7 +8,7 @@ use rocket::{serde::json::Json, State}; /// Fetch an invite by its id. #[openapi(tag = "Invites")] #[get("/")] -pub async fn fetch(db: &State, target: Reference) -> Result> { +pub async fn fetch(db: &State, target: Reference<'_>) -> Result> { Ok(Json(match target.as_invite(db).await? { Invite::Server { channel, creator, .. @@ -27,7 +27,7 @@ pub async fn fetch(db: &State, target: Reference) -> Result, target: Reference) -> Result v0::InviteResponse::Group { - code: target.id, + code: target.id.to_string(), channel_id: id, channel_name: name, channel_description: description, diff --git a/crates/delta/src/routes/invites/invite_join.rs b/crates/delta/src/routes/invites/invite_join.rs index 83b59195..a18213f3 100644 --- a/crates/delta/src/routes/invites/invite_join.rs +++ b/crates/delta/src/routes/invites/invite_join.rs @@ -12,7 +12,7 @@ pub async fn join( db: &State, amqp: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { if user.bot.is_some() { return Err(create_error!(IsBot)); diff --git a/crates/delta/src/routes/servers/ban_create.rs b/crates/delta/src/routes/servers/ban_create.rs index 6e530b1a..727b3fb9 100644 --- a/crates/delta/src/routes/servers/ban_create.rs +++ b/crates/delta/src/routes/servers/ban_create.rs @@ -19,8 +19,8 @@ pub async fn ban( db: &State, voice_client: &State, user: User, - server: Reference, - target: Reference, + server: Reference<'_>, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -65,7 +65,7 @@ pub async fn ban( } } - ServerBan::create(db, &server, &target.id, data.reason) + ServerBan::create(db, &server, target.id, data.reason) .await .map(Into::into) .map(Json) diff --git a/crates/delta/src/routes/servers/ban_list.rs b/crates/delta/src/routes/servers/ban_list.rs index 457fd98e..827e7dc3 100644 --- a/crates/delta/src/routes/servers/ban_list.rs +++ b/crates/delta/src/routes/servers/ban_list.rs @@ -17,7 +17,7 @@ use rocket::State; pub async fn list( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { let server = target.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/ban_remove.rs b/crates/delta/src/routes/servers/ban_remove.rs index 3b1b7285..f01bc8b0 100644 --- a/crates/delta/src/routes/servers/ban_remove.rs +++ b/crates/delta/src/routes/servers/ban_remove.rs @@ -15,8 +15,8 @@ use rocket_empty::EmptyResponse; pub async fn unban( db: &State, user: User, - server: Reference, - target: Reference, + server: Reference<'_>, + target: Reference<'_>, ) -> Result { let server = server.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/channel_create.rs b/crates/delta/src/routes/servers/channel_create.rs index ae35bb46..53aa616d 100644 --- a/crates/delta/src/routes/servers/channel_create.rs +++ b/crates/delta/src/routes/servers/channel_create.rs @@ -16,7 +16,7 @@ use validator::Validate; pub async fn create_server_channel( db: &State, user: User, - server: Reference, + server: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); diff --git a/crates/delta/src/routes/servers/emoji_list.rs b/crates/delta/src/routes/servers/emoji_list.rs index 405e5d43..bd19c73e 100644 --- a/crates/delta/src/routes/servers/emoji_list.rs +++ b/crates/delta/src/routes/servers/emoji_list.rs @@ -15,7 +15,7 @@ use rocket::{serde::json::Json, State}; pub async fn list_emoji( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result>> { let server = target.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/invites_fetch.rs b/crates/delta/src/routes/servers/invites_fetch.rs index 05958485..b6314207 100644 --- a/crates/delta/src/routes/servers/invites_fetch.rs +++ b/crates/delta/src/routes/servers/invites_fetch.rs @@ -15,7 +15,7 @@ use rocket::{serde::json::Json, State}; pub async fn invites( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result>> { let server = target.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/member_edit.rs b/crates/delta/src/routes/servers/member_edit.rs index 1ba00b73..9b0248a4 100644 --- a/crates/delta/src/routes/servers/member_edit.rs +++ b/crates/delta/src/routes/servers/member_edit.rs @@ -31,8 +31,8 @@ pub async fn edit( db: &State, voice_client: &State, user: User, - server: Reference, - member: Reference, + server: Reference<'_>, + member: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -52,13 +52,7 @@ pub async fn edit( let permissions = calculate_server_permissions(&mut query).await; // Check permissions in server - if data.nickname.is_some() - || data - .remove - .as_ref() - .map(|x| x.contains(&v0::FieldsMember::Nickname)) - .unwrap_or_default() - { + if data.nickname.is_some() || data.remove.contains(&v0::FieldsMember::Nickname) { if user.id == member.id.user { permissions.throw_if_lacking_channel_permission(ChannelPermission::ChangeNickname)?; } else { @@ -66,13 +60,7 @@ pub async fn edit( } } - if data.avatar.is_some() - || data - .remove - .as_ref() - .map(|x| x.contains(&v0::FieldsMember::Avatar)) - .unwrap_or_default() - { + if data.avatar.is_some() || data.remove.contains(&v0::FieldsMember::Avatar) { if user.id == member.id.user { permissions.throw_if_lacking_channel_permission(ChannelPermission::ChangeAvatar)?; } else { @@ -80,23 +68,11 @@ pub async fn edit( } } - if data.roles.is_some() - || data - .remove - .as_ref() - .map(|x| x.contains(&v0::FieldsMember::Roles)) - .unwrap_or_default() - { + if data.roles.is_some() || data.remove.contains(&v0::FieldsMember::Roles) { permissions.throw_if_lacking_channel_permission(ChannelPermission::AssignRoles)?; } - if data.timeout.is_some() - || data - .remove - .as_ref() - .map(|x| x.contains(&v0::FieldsMember::Timeout)) - .unwrap_or_default() - { + if data.timeout.is_some() || data.remove.contains(&v0::FieldsMember::Timeout) { if data.timeout.is_some() && member.id.user == user.id { return Err(create_error!(CannotTimeoutYourself)); } @@ -121,7 +97,7 @@ pub async fn edit( // ensure the channel we are moving them to is in the server and is a voice channel - let channel = Reference::from_unchecked(new_channel.clone()) + let channel = Reference::from_unchecked(new_channel) .as_channel(db) .await .map_err(|_| create_error!(UnknownChannel))?; @@ -192,11 +168,9 @@ pub async fn edit( }; // 1. Remove fields from object - if let Some(fields) = &remove { - if fields.contains(&v0::FieldsMember::Avatar) { - if let Some(avatar) = &member.avatar { - db.mark_attachment_as_deleted(&avatar.id).await?; - } + if remove.contains(&v0::FieldsMember::Avatar) { + if let Some(avatar) = &member.avatar { + db.mark_attachment_as_deleted(&avatar.id).await?; } } @@ -205,19 +179,10 @@ pub async fn edit( partial.avatar = Some(File::use_user_avatar(db, &avatar, &user.id, &user.id).await?); } - let remove_contains_voice = remove - .as_ref() - .map(|r| r.contains(FieldsMember::CanPublish) || r.contains(FieldsMember::CanReceive)) - .unwrap_or_default(); + let remove_contains_voice = remove.contains(FieldsMember::CanPublish) || remove.contains(FieldsMember::CanReceive); member - .update( - db, - partial, - remove - .map(|v| v.into_iter().map(Into::into).collect()) - .unwrap_or_default(), - ) + .update(db, partial, remove.into_iter().map(Into::into).collect()) .await?; if let Some(new_voice_channel) = new_voice_channel { @@ -261,7 +226,7 @@ pub async fn edit( if let Some(channel) = get_user_voice_channel_in_server(&target_user.id, &server.id).await? { let node = get_channel_node(&channel).await?.unwrap(); - let channel = Reference::from_unchecked(channel).as_channel(db).await?; + let channel = Reference::from_unchecked(&channel).as_channel(db).await?; sync_user_voice_permissions( db, diff --git a/crates/delta/src/routes/servers/member_experimental_query.rs b/crates/delta/src/routes/servers/member_experimental_query.rs index 125b8db9..8126b9f2 100644 --- a/crates/delta/src/routes/servers/member_experimental_query.rs +++ b/crates/delta/src/routes/servers/member_experimental_query.rs @@ -36,7 +36,7 @@ pub struct MemberQueryResponse { pub async fn member_experimental_query( db: &State, user: User, - target: Reference, + target: Reference<'_>, options: OptionsQueryMembers, ) -> Result> { if !options.experimental_api { diff --git a/crates/delta/src/routes/servers/member_fetch.rs b/crates/delta/src/routes/servers/member_fetch.rs index b1f39740..c05935be 100644 --- a/crates/delta/src/routes/servers/member_fetch.rs +++ b/crates/delta/src/routes/servers/member_fetch.rs @@ -15,8 +15,8 @@ use rocket::{serde::json::Json, State}; pub async fn fetch( db: &State, user: User, - target: Reference, - member: Reference, + target: Reference<'_>, + member: Reference<'_>, roles: Option, ) -> Result> { let server = target.as_server(db).await?; diff --git a/crates/delta/src/routes/servers/member_fetch_all.rs b/crates/delta/src/routes/servers/member_fetch_all.rs index 29997668..cc85b968 100644 --- a/crates/delta/src/routes/servers/member_fetch_all.rs +++ b/crates/delta/src/routes/servers/member_fetch_all.rs @@ -15,7 +15,7 @@ use rocket::{serde::json::Json, State}; pub async fn fetch_all( db: &State, user: User, - target: Reference, + target: Reference<'_>, options: v0::OptionsFetchAllMembers, ) -> Result> { let server = target.as_server(db).await?; diff --git a/crates/delta/src/routes/servers/member_remove.rs b/crates/delta/src/routes/servers/member_remove.rs index 1f8ea9ee..1ef7683b 100644 --- a/crates/delta/src/routes/servers/member_remove.rs +++ b/crates/delta/src/routes/servers/member_remove.rs @@ -17,8 +17,8 @@ pub async fn kick( db: &State, voice_client: &State, user: User, - target: Reference, - member: Reference, + target: Reference<'_>, + member: Reference<'_>, ) -> Result { let server = target.as_server(db).await?; diff --git a/crates/delta/src/routes/servers/mod.rs b/crates/delta/src/routes/servers/mod.rs index 066fd32a..78b96dbd 100644 --- a/crates/delta/src/routes/servers/mod.rs +++ b/crates/delta/src/routes/servers/mod.rs @@ -17,8 +17,8 @@ mod permissions_set_default; mod roles_create; mod roles_delete; mod roles_edit; -mod roles_fetch; mod roles_edit_positions; +mod roles_fetch; mod server_ack; mod server_create; mod server_delete; @@ -47,7 +47,7 @@ pub fn routes() -> (Vec, OpenApi) { roles_fetch::fetch, roles_delete::delete, permissions_set::set_role_permission, - permissions_set_default::set_default_permissions, + permissions_set_default::set_default_server_permissions, emoji_list::list_emoji, roles_edit_positions::edit_role_ranks ] diff --git a/crates/delta/src/routes/servers/permissions_set.rs b/crates/delta/src/routes/servers/permissions_set.rs index 3d80d387..50d7eac8 100644 --- a/crates/delta/src/routes/servers/permissions_set.rs +++ b/crates/delta/src/routes/servers/permissions_set.rs @@ -15,7 +15,7 @@ pub async fn set_role_permission( db: &State, voice_client: &State, user: User, - target: Reference, + target: Reference<'_>, role_id: String, data: Json, ) -> Result> { @@ -41,7 +41,7 @@ pub async fn set_role_permission( .await?; for channel_id in &server.channels { - let channel = Reference::from_unchecked(channel_id.clone()).as_channel(db).await?; + let channel = Reference::from_unchecked(channel_id).as_channel(db).await?; sync_voice_permissions(db, voice_client, &channel, Some(&server), Some(&role_id)).await?; }; diff --git a/crates/delta/src/routes/servers/permissions_set_default.rs b/crates/delta/src/routes/servers/permissions_set_default.rs index 42c364d8..aeeb50c6 100644 --- a/crates/delta/src/routes/servers/permissions_set_default.rs +++ b/crates/delta/src/routes/servers/permissions_set_default.rs @@ -13,11 +13,11 @@ use rocket::{serde::json::Json, State}; /// Sets permissions for the default role in this server. #[openapi(tag = "Server Permissions")] #[put("//permissions/default", data = "", rank = 1)] -pub async fn set_default_permissions( +pub async fn set_default_server_permissions( db: &State, voice_client: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -40,7 +40,7 @@ pub async fn set_default_permissions( .await?; for channel_id in &server.channels { - let channel = Reference::from_unchecked(channel_id.clone()).as_channel(db).await?; + let channel = Reference::from_unchecked(channel_id).as_channel(db).await?; sync_voice_permissions(db, voice_client, &channel, Some(&server), None).await?; }; diff --git a/crates/delta/src/routes/servers/roles_create.rs b/crates/delta/src/routes/servers/roles_create.rs index c7c67f09..e68d5ea6 100644 --- a/crates/delta/src/routes/servers/roles_create.rs +++ b/crates/delta/src/routes/servers/roles_create.rs @@ -17,7 +17,7 @@ use validator::Validate; pub async fn create( db: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -40,20 +40,10 @@ pub async fn create( })); }; - let member_rank = query.get_member_rank(); - let rank = if let Some(given_rank) = data.rank { - if given_rank <= member_rank.unwrap_or(i64::MIN) { - return Err(create_error!(NotElevated)); - } - - given_rank - } else { - member_rank.unwrap_or(0).saturating_add(1) - }; - let role = Role { name: data.name, - rank, + // Rank of the new role should be below the lowest role + rank: server.roles.len() as i64, colour: None, hoist: false, permissions: Default::default(), diff --git a/crates/delta/src/routes/servers/roles_delete.rs b/crates/delta/src/routes/servers/roles_delete.rs index 38b40859..f1ec5517 100644 --- a/crates/delta/src/routes/servers/roles_delete.rs +++ b/crates/delta/src/routes/servers/roles_delete.rs @@ -16,7 +16,7 @@ use rocket_empty::EmptyResponse; pub async fn delete( db: &State, user: User, - target: Reference, + target: Reference<'_>, role_id: String, voice_client: &State ) -> Result { @@ -34,7 +34,7 @@ pub async fn delete( } for channel_id in &server.channels { - let channel = Reference::from_unchecked(channel_id.clone()).as_channel(db).await?; + let channel = Reference::from_unchecked(channel_id).as_channel(db).await?; sync_voice_permissions(db, voice_client, &channel, Some(&server), Some(&role_id)).await?; }; diff --git a/crates/delta/src/routes/servers/roles_edit.rs b/crates/delta/src/routes/servers/roles_edit.rs index db0fca9d..639589af 100644 --- a/crates/delta/src/routes/servers/roles_edit.rs +++ b/crates/delta/src/routes/servers/roles_edit.rs @@ -18,7 +18,7 @@ pub async fn edit( db: &State, voice_client: &State, user: User, - target: Reference, + target: Reference<'_>, role_id: String, data: Json, ) -> Result> { @@ -63,14 +63,12 @@ pub async fn edit( &server.id, &role_id, partial, - remove - .map(|v| v.into_iter().map(Into::into).collect()) - .unwrap_or_default(), + remove.into_iter().map(Into::into).collect(), ) .await?; for channel_id in &server.channels { - let channel = Reference::from_unchecked(channel_id.clone()).as_channel(db).await?; + let channel = Reference::from_unchecked(channel_id).as_channel(db).await?; sync_voice_permissions(db, voice_client, &channel, Some(&server), Some(&role_id)).await?; }; diff --git a/crates/delta/src/routes/servers/roles_edit_positions.rs b/crates/delta/src/routes/servers/roles_edit_positions.rs index 59614162..d27259e5 100644 --- a/crates/delta/src/routes/servers/roles_edit_positions.rs +++ b/crates/delta/src/routes/servers/roles_edit_positions.rs @@ -15,7 +15,7 @@ use rocket::{serde::json::Json, State}; pub async fn edit_role_ranks( db: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); diff --git a/crates/delta/src/routes/servers/roles_fetch.rs b/crates/delta/src/routes/servers/roles_fetch.rs index 5c646b44..d26365a9 100644 --- a/crates/delta/src/routes/servers/roles_fetch.rs +++ b/crates/delta/src/routes/servers/roles_fetch.rs @@ -15,7 +15,7 @@ use rocket::{serde::json::Json, State}; pub async fn fetch( db: &State, user: User, - target: Reference, + target: Reference<'_>, role_id: String, ) -> Result> { let mut server = target.as_server(db).await?; diff --git a/crates/delta/src/routes/servers/server_ack.rs b/crates/delta/src/routes/servers/server_ack.rs index d70eefec..789617e1 100644 --- a/crates/delta/src/routes/servers/server_ack.rs +++ b/crates/delta/src/routes/servers/server_ack.rs @@ -12,7 +12,7 @@ use rocket_empty::EmptyResponse; /// Mark all channels in a server as read. #[openapi(tag = "Server Information")] #[put("//ack")] -pub async fn ack(db: &State, user: User, target: Reference) -> Result { +pub async fn ack(db: &State, user: User, target: Reference<'_>) -> Result { if user.bot.is_some() { return Err(create_error!(IsBot)); } diff --git a/crates/delta/src/routes/servers/server_delete.rs b/crates/delta/src/routes/servers/server_delete.rs index 667a171f..58898984 100644 --- a/crates/delta/src/routes/servers/server_delete.rs +++ b/crates/delta/src/routes/servers/server_delete.rs @@ -18,11 +18,11 @@ pub async fn delete( db: &State, voice_client: &State, user: User, - target: Reference, + target: Reference<'_>, options: v0::OptionsServerDelete, ) -> Result { let server = target.as_server(db).await?; - let member = db.fetch_member(&target.id, &user.id).await?; + let member = db.fetch_member(target.id, &user.id).await?; if server.owner == user.id { for channel_id in &server.channels { diff --git a/crates/delta/src/routes/servers/server_edit.rs b/crates/delta/src/routes/servers/server_edit.rs index 05688473..23d79c34 100644 --- a/crates/delta/src/routes/servers/server_edit.rs +++ b/crates/delta/src/routes/servers/server_edit.rs @@ -18,7 +18,7 @@ use validator::Validate; pub async fn edit( db: &State, user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -43,7 +43,7 @@ pub async fn edit( && data.flags.is_none() && data.analytics.is_none() && data.discoverable.is_none() - && data.remove.is_none() + && data.remove.is_empty() { return Ok(Json(server.into())); } else if data.name.is_some() @@ -52,7 +52,7 @@ pub async fn edit( || data.banner.is_some() || data.system_messages.is_some() || data.analytics.is_some() - || data.remove.is_some() + || !data.remove.is_empty() { permissions.throw_if_lacking_channel_permission(ChannelPermission::ManageServer)?; } @@ -96,17 +96,15 @@ pub async fn edit( }; // 1. Remove fields from object - if let Some(fields) = &remove { - if fields.contains(&v0::FieldsServer::Banner) { - if let Some(banner) = &server.banner { - db.mark_attachment_as_deleted(&banner.id).await?; - } + if remove.contains(&v0::FieldsServer::Banner) { + if let Some(banner) = &server.banner { + db.mark_attachment_as_deleted(&banner.id).await?; } + } - if fields.contains(&v0::FieldsServer::Icon) { - if let Some(icon) = &server.icon { - db.mark_attachment_as_deleted(&icon.id).await?; - } + if remove.contains(&v0::FieldsServer::Icon) { + if let Some(icon) = &server.icon { + db.mark_attachment_as_deleted(&icon.id).await?; } } @@ -149,13 +147,7 @@ pub async fn edit( } server - .update( - db, - partial, - remove - .map(|v| v.into_iter().map(Into::into).collect()) - .unwrap_or_default(), - ) + .update(db, partial, remove.into_iter().map(Into::into).collect()) .await?; Ok(Json(server.into())) diff --git a/crates/delta/src/routes/servers/server_fetch.rs b/crates/delta/src/routes/servers/server_fetch.rs index e668021c..82eb0c7c 100644 --- a/crates/delta/src/routes/servers/server_fetch.rs +++ b/crates/delta/src/routes/servers/server_fetch.rs @@ -15,7 +15,7 @@ use rocket::{serde::json::Json, State}; pub async fn fetch( db: &State, user: User, - target: Reference, + target: Reference<'_>, options: v0::OptionsFetchServer, ) -> Result> { let server = target.as_server(db).await?; diff --git a/crates/delta/src/routes/users/add_friend.rs b/crates/delta/src/routes/users/add_friend.rs index b7728d0e..946c3296 100644 --- a/crates/delta/src/routes/users/add_friend.rs +++ b/crates/delta/src/routes/users/add_friend.rs @@ -14,7 +14,7 @@ pub async fn add( db: &State, amqp: &State, mut user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { let mut target = target.as_user(db).await?; diff --git a/crates/delta/src/routes/users/block_user.rs b/crates/delta/src/routes/users/block_user.rs index 0e6498aa..cfce993c 100644 --- a/crates/delta/src/routes/users/block_user.rs +++ b/crates/delta/src/routes/users/block_user.rs @@ -13,7 +13,7 @@ use rocket::State; pub async fn block( db: &State, mut user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { let mut target = target.as_user(db).await?; diff --git a/crates/delta/src/routes/users/edit_user.rs b/crates/delta/src/routes/users/edit_user.rs index aa91e3f8..535fc05c 100644 --- a/crates/delta/src/routes/users/edit_user.rs +++ b/crates/delta/src/routes/users/edit_user.rs @@ -14,7 +14,7 @@ use validator::Validate; pub async fn edit( db: &State, mut user: User, - target: Reference, + target: Reference<'_>, data: Json, ) -> Result> { let data = data.into_inner(); @@ -53,31 +53,29 @@ pub async fn edit( && data.avatar.is_none() && data.badges.is_none() && data.flags.is_none() - && data.remove.is_none() + && data.remove.is_empty() { return Ok(Json(user.into_self(false).await)); } // 1. Remove fields from object - if let Some(fields) = &data.remove { - if fields.contains(&v0::FieldsUser::Avatar) { - if let Some(avatar) = &user.avatar { - db.mark_attachment_as_deleted(&avatar.id).await?; + if data.remove.contains(&v0::FieldsUser::Avatar) { + if let Some(avatar) = &user.avatar { + db.mark_attachment_as_deleted(&avatar.id).await?; + } + } + + if data.remove.contains(&v0::FieldsUser::ProfileBackground) { + if let Some(profile) = &user.profile { + if let Some(background) = &profile.background { + db.mark_attachment_as_deleted(&background.id).await?; } } + } - if fields.contains(&v0::FieldsUser::ProfileBackground) { - if let Some(profile) = &user.profile { - if let Some(background) = &profile.background { - db.mark_attachment_as_deleted(&background.id).await?; - } - } - } - - for field in fields { - let field: FieldsUser = field.clone().into(); - user.remove_field(&field); - } + for field in &data.remove { + let field: FieldsUser = field.clone().into(); + user.remove_field(&field); } let mut partial: PartialUser = PartialUser { @@ -124,9 +122,7 @@ pub async fn edit( user.update( db, partial, - data.remove - .map(|v| v.into_iter().map(Into::into).collect()) - .unwrap_or_default(), + data.remove.into_iter().map(Into::into).collect(), ) .await?; diff --git a/crates/delta/src/routes/users/fetch_profile.rs b/crates/delta/src/routes/users/fetch_profile.rs index 66acacfa..e0718d4b 100644 --- a/crates/delta/src/routes/users/fetch_profile.rs +++ b/crates/delta/src/routes/users/fetch_profile.rs @@ -17,7 +17,7 @@ use rocket::{serde::json::Json, State}; pub async fn profile( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { if user.id == target.id { return Ok(Json(user.profile.map(Into::into).unwrap_or_default())); diff --git a/crates/delta/src/routes/users/fetch_user.rs b/crates/delta/src/routes/users/fetch_user.rs index 68be67b9..e6aba68e 100644 --- a/crates/delta/src/routes/users/fetch_user.rs +++ b/crates/delta/src/routes/users/fetch_user.rs @@ -13,7 +13,7 @@ use rocket::{serde::json::Json, State}; /// Retrieve a user's information. #[openapi(tag = "User Information")] #[get("/")] -pub async fn fetch(db: &State, user: User, target: Reference) -> Result> { +pub async fn fetch(db: &State, user: User, target: Reference<'_>) -> Result> { if user.id == target.id { return Ok(Json(user.into_self(false).await)); } diff --git a/crates/delta/src/routes/users/fetch_user_flags.rs b/crates/delta/src/routes/users/fetch_user_flags.rs index 92377a57..df021abb 100644 --- a/crates/delta/src/routes/users/fetch_user_flags.rs +++ b/crates/delta/src/routes/users/fetch_user_flags.rs @@ -10,7 +10,7 @@ use rocket::{serde::json::Json, State}; #[get("//flags")] pub async fn fetch_user_flags( db: &State, - target: Reference, + target: Reference<'_>, ) -> Result> { let flags = if let Ok(target) = target.as_user(db).await { target.flags.unwrap_or_default() diff --git a/crates/delta/src/routes/users/find_mutual.rs b/crates/delta/src/routes/users/find_mutual.rs index 8f3de313..9f7fd950 100644 --- a/crates/delta/src/routes/users/find_mutual.rs +++ b/crates/delta/src/routes/users/find_mutual.rs @@ -16,7 +16,7 @@ use rocket::State; pub async fn mutual( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { if target.id == user.id { return Err(create_error!(InvalidOperation)); diff --git a/crates/delta/src/routes/users/open_dm.rs b/crates/delta/src/routes/users/open_dm.rs index a01fa09a..78486523 100644 --- a/crates/delta/src/routes/users/open_dm.rs +++ b/crates/delta/src/routes/users/open_dm.rs @@ -17,7 +17,7 @@ use rocket::{serde::json::Json, State}; pub async fn open_dm( db: &State, user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { let target = target.as_user(db).await?; diff --git a/crates/delta/src/routes/users/remove_friend.rs b/crates/delta/src/routes/users/remove_friend.rs index 6ae38eeb..59b85ecb 100644 --- a/crates/delta/src/routes/users/remove_friend.rs +++ b/crates/delta/src/routes/users/remove_friend.rs @@ -13,7 +13,7 @@ use rocket::State; pub async fn remove( db: &State, mut user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { let mut target = target.as_user(db).await?; diff --git a/crates/delta/src/routes/users/unblock_user.rs b/crates/delta/src/routes/users/unblock_user.rs index d379c665..a464ecc5 100644 --- a/crates/delta/src/routes/users/unblock_user.rs +++ b/crates/delta/src/routes/users/unblock_user.rs @@ -13,7 +13,7 @@ use rocket::State; pub async fn unblock( db: &State, mut user: User, - target: Reference, + target: Reference<'_>, ) -> Result> { let mut target = target.as_user(db).await?; diff --git a/crates/delta/src/routes/webhooks/webhook_delete.rs b/crates/delta/src/routes/webhooks/webhook_delete.rs index 2a5bbc35..fcd428d3 100644 --- a/crates/delta/src/routes/webhooks/webhook_delete.rs +++ b/crates/delta/src/routes/webhooks/webhook_delete.rs @@ -15,7 +15,7 @@ use rocket_empty::EmptyResponse; pub async fn webhook_delete( db: &State, user: User, - webhook_id: Reference, + webhook_id: Reference<'_>, ) -> Result { let webhook = webhook_id.as_webhook(db).await?; let channel = db.fetch_channel(&webhook.channel_id).await?; diff --git a/crates/delta/src/routes/webhooks/webhook_delete_token.rs b/crates/delta/src/routes/webhooks/webhook_delete_token.rs index c5435302..aa5fc2e9 100644 --- a/crates/delta/src/routes/webhooks/webhook_delete_token.rs +++ b/crates/delta/src/routes/webhooks/webhook_delete_token.rs @@ -10,7 +10,7 @@ use rocket_empty::EmptyResponse; #[delete("//")] pub async fn webhook_delete_token( db: &State, - webhook_id: Reference, + webhook_id: Reference<'_>, token: String, ) -> Result { let webhook = webhook_id.as_webhook(db).await?; diff --git a/crates/delta/src/routes/webhooks/webhook_edit.rs b/crates/delta/src/routes/webhooks/webhook_edit.rs index 42a54f1a..aa06930a 100644 --- a/crates/delta/src/routes/webhooks/webhook_edit.rs +++ b/crates/delta/src/routes/webhooks/webhook_edit.rs @@ -15,7 +15,7 @@ use validator::Validate; #[patch("/", data = "")] pub async fn webhook_edit( db: &State, - webhook_id: Reference, + webhook_id: Reference<'_>, user: User, data: Json, ) -> Result> { diff --git a/crates/delta/src/routes/webhooks/webhook_edit_token.rs b/crates/delta/src/routes/webhooks/webhook_edit_token.rs index 8690f420..4f4dde0d 100644 --- a/crates/delta/src/routes/webhooks/webhook_edit_token.rs +++ b/crates/delta/src/routes/webhooks/webhook_edit_token.rs @@ -12,7 +12,7 @@ use rocket::{serde::json::Json, State}; #[patch("//", data = "")] pub async fn webhook_edit_token( db: &State, - webhook_id: Reference, + webhook_id: Reference<'_>, token: String, data: Json, ) -> Result> { diff --git a/crates/delta/src/routes/webhooks/webhook_execute.rs b/crates/delta/src/routes/webhooks/webhook_execute.rs index 4d64688d..f46004f7 100644 --- a/crates/delta/src/routes/webhooks/webhook_execute.rs +++ b/crates/delta/src/routes/webhooks/webhook_execute.rs @@ -18,7 +18,7 @@ use validator::Validate; pub async fn webhook_execute( db: &State, amqp: &State, - webhook_id: Reference, + webhook_id: Reference<'_>, token: String, data: Json, idempotency: IdempotencyKey, diff --git a/crates/delta/src/routes/webhooks/webhook_execute_github.rs b/crates/delta/src/routes/webhooks/webhook_execute_github.rs index cde16548..f84ecc63 100644 --- a/crates/delta/src/routes/webhooks/webhook_execute_github.rs +++ b/crates/delta/src/routes/webhooks/webhook_execute_github.rs @@ -752,7 +752,7 @@ fn convert_event(data: &str, event_name: &str) -> Result { pub async fn webhook_execute_github( db: &State, amqp: &State, - webhook_id: Reference, + webhook_id: Reference<'_>, token: String, event: EventHeader<'_>, data: String, diff --git a/crates/delta/src/routes/webhooks/webhook_fetch.rs b/crates/delta/src/routes/webhooks/webhook_fetch.rs index 28afad2f..c8569e17 100644 --- a/crates/delta/src/routes/webhooks/webhook_fetch.rs +++ b/crates/delta/src/routes/webhooks/webhook_fetch.rs @@ -14,7 +14,7 @@ use rocket::{serde::json::Json, State}; #[get("/")] pub async fn webhook_fetch( db: &State, - webhook_id: Reference, + webhook_id: Reference<'_>, user: User, ) -> Result> { let webhook = webhook_id.as_webhook(db).await?; diff --git a/crates/delta/src/routes/webhooks/webhook_fetch_token.rs b/crates/delta/src/routes/webhooks/webhook_fetch_token.rs index 3ccec4f3..70c95825 100644 --- a/crates/delta/src/routes/webhooks/webhook_fetch_token.rs +++ b/crates/delta/src/routes/webhooks/webhook_fetch_token.rs @@ -10,7 +10,7 @@ use rocket::{serde::json::Json, State}; #[get("//")] pub async fn webhook_fetch_token( db: &State, - webhook_id: Reference, + webhook_id: Reference<'_>, token: String, ) -> Result> { let webhook = webhook_id.as_webhook(db).await?; diff --git a/default.nix b/default.nix index f8736308..dad66fc2 100644 --- a/default.nix +++ b/default.nix @@ -1,9 +1,12 @@ -{ pkgs ? import {} }: +{ + pkgs ? import { }, +}: pkgs.mkShell rec { buildInputs = [ # Tools pkgs.git + pkgs.just # Cargo pkgs.cargo diff --git a/scripts/try-tag-and-release.sh b/scripts/try-tag-and-release.sh index 54c7adc8..2ab91845 100755 --- a/scripts/try-tag-and-release.sh +++ b/scripts/try-tag-and-release.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash date=$(date +'%Y%m%d') incr=1