Compare commits

...
4 Commits
14 changed files with 73 additions and 52 deletions

No files matched your search

+2
View File
@@ -1,3 +1,5 @@
Rocket.toml Rocket.toml
target target
.data .data
.vercel
@@ -2,13 +2,27 @@ use revolt_quark::{
models::{channel::PartialChannel, Channel, User}, models::{channel::PartialChannel, Channel, User},
perms, Db, EmptyResponse, Error, Permission, Ref, Result, perms, Db, EmptyResponse, Error, Permission, Ref, Result,
}; };
use serde::{Deserialize, Serialize};
use validator::Validate;
/// # Query Parameters
#[derive(Validate, Serialize, Deserialize, JsonSchema, FromForm)]
pub struct OptionsChannelDelete {
/// Whether to not send a leave message
leave_silently: Option<bool>,
}
/// # Close Channel /// # Close Channel
/// ///
/// Deletes a server channel, leaves a group or closes a group. /// Deletes a server channel, leaves a group or closes a group.
#[openapi(tag = "Channel Information")] #[openapi(tag = "Channel Information")]
#[delete("/<target>")] #[delete("/<target>?<options..>")]
pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> { pub async fn req(
db: &Db,
user: User,
target: Ref,
options: OptionsChannelDelete,
) -> Result<EmptyResponse> {
let mut channel = target.as_channel(db).await?; let mut channel = target.as_channel(db).await?;
let mut perms = perms(&user).channel(&channel); let mut perms = perms(&user).channel(&channel);
perms.throw_permission(db, Permission::ViewChannel).await?; perms.throw_permission(db, Permission::ViewChannel).await?;
@@ -27,7 +41,12 @@ pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
.await .await
.map(|_| EmptyResponse), .map(|_| EmptyResponse),
Channel::Group { .. } => channel Channel::Group { .. } => channel
.remove_user_from_group(db, &user.id, None) .remove_user_from_group(
db,
&user.id,
None,
options.leave_silently.unwrap_or_default(),
)
.await .await
.map(|_| EmptyResponse), .map(|_| EmptyResponse),
Channel::TextChannel { .. } | Channel::VoiceChannel { .. } => { Channel::TextChannel { .. } | Channel::VoiceChannel { .. } => {
@@ -29,6 +29,8 @@ pub struct DataEditChannel {
icon: Option<String>, icon: Option<String>,
/// Whether this channel is age-restricted /// Whether this channel is age-restricted
nsfw: Option<bool>, nsfw: Option<bool>,
/// Whether this channel is archived
archived: Option<bool>,
#[validate(length(min = 1))] #[validate(length(min = 1))]
remove: Option<Vec<FieldsChannel>>, remove: Option<Vec<FieldsChannel>>,
} }
@@ -33,7 +33,7 @@ pub async fn req(db: &Db, user: User, target: Ref, member: Ref) -> Result<EmptyR
} }
channel channel
.remove_user_from_group(db, &member.id, Some(&user.id)) .remove_user_from_group(db, &member.id, Some(&user.id), false)
.await .await
.map(|_| EmptyResponse) .map(|_| EmptyResponse)
} }
@@ -34,7 +34,7 @@ pub async fn req(db: &Db, user: User, target: Ref, member: Ref) -> Result<EmptyR
} }
server server
.remove_member(db, member, RemovalIntention::Kick) .remove_member(db, member, RemovalIntention::Kick, false)
.await .await
.map(|_| EmptyResponse) .map(|_| EmptyResponse)
} }
@@ -2,13 +2,27 @@ use revolt_quark::{
models::{server_member::RemovalIntention, User}, models::{server_member::RemovalIntention, User},
Db, EmptyResponse, Ref, Result, Db, EmptyResponse, Ref, Result,
}; };
use serde::{Deserialize, Serialize};
use validator::Validate;
/// # Query Parameters
#[derive(Validate, Serialize, Deserialize, JsonSchema, FromForm)]
pub struct OptionsServerDelete {
/// Whether to not send a leave message
leave_silently: Option<bool>,
}
/// # Delete / Leave Server /// # Delete / Leave Server
/// ///
/// Deletes a server if owner otherwise leaves. /// Deletes a server if owner otherwise leaves.
#[openapi(tag = "Server Information")] #[openapi(tag = "Server Information")]
#[delete("/<target>")] #[delete("/<target>?<options..>")]
pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> { pub async fn req(
db: &Db,
user: User,
target: Ref,
options: OptionsServerDelete,
) -> Result<EmptyResponse> {
let server = target.as_server(db).await?; 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?;
@@ -16,7 +30,12 @@ pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
server.delete(db).await server.delete(db).await
} else { } else {
server server
.remove_member(db, member, RemovalIntention::Leave) .remove_member(
db,
member,
RemovalIntention::Leave,
options.leave_silently.unwrap_or_default(),
)
.await .await
} }
.map(|_| EmptyResponse) .map(|_| EmptyResponse)
@@ -138,12 +138,15 @@ pub async fn req(
} }
// 2. Validate changes // 2. Validate changes
let mut unknown_channels = HashSet::new();
if let Some(system_messages) = &partial.system_messages { if let Some(system_messages) = &partial.system_messages {
unknown_channels = system_messages.clone().into_channel_ids(); for id in system_messages.clone().into_channel_ids() {
if !server.channels.contains(&id) {
return Err(Error::NotFound);
}
}
} }
if let Some(categories) = &partial.categories { if let Some(categories) = &mut partial.categories {
let mut channel_ids = HashSet::new(); let mut channel_ids = HashSet::new();
for category in categories { for category in categories {
for channel in &category.channels { for channel in &category.channels {
@@ -153,13 +156,11 @@ pub async fn req(
channel_ids.insert(channel.to_string()); channel_ids.insert(channel.to_string());
} }
}
unknown_channels.extend(channel_ids); category
.channels
.retain(|item| server.channels.contains(item));
} }
if !db.check_channels_exist(&unknown_channels).await? {
return Err(Error::NotFound);
} }
// 3. Apply new icon // 3. Apply new icon
@@ -1,5 +1,3 @@
use std::collections::HashSet;
use crate::models::channel::{Channel, FieldsChannel, PartialChannel}; use crate::models::channel::{Channel, FieldsChannel, PartialChannel};
use crate::{AbstractAttachment, AbstractChannel, Error, OverrideField, Result}; use crate::{AbstractAttachment, AbstractChannel, Error, OverrideField, Result};
@@ -83,8 +81,4 @@ impl AbstractChannel for DummyDb {
info!("Updating permissions for role {role} in {channel} with {permissions:?}"); info!("Updating permissions for role {role} in {channel} with {permissions:?}");
Ok(()) Ok(())
} }
async fn check_channels_exist(&self, _channels: &HashSet<String>) -> Result<bool> {
Ok(true)
}
} }
@@ -286,6 +286,7 @@ impl Channel {
db: &Database, db: &Database,
user: &str, user: &str,
by: Option<&str>, by: Option<&str>,
silent: bool,
) -> Result<()> { ) -> Result<()> {
match &self { match &self {
Channel::Group { Channel::Group {
@@ -329,6 +330,7 @@ impl Channel {
.p(id.to_string()) .p(id.to_string())
.await; .await;
if !silent {
if let Some(by) = by { if let Some(by) = by {
SystemMessage::UserRemove { SystemMessage::UserRemove {
id: user.to_string(), id: user.to_string(),
@@ -343,6 +345,7 @@ impl Channel {
.create(db, self, None) .create(db, self, None)
.await .await
.ok(); .ok();
}
Ok(()) Ok(())
} }
@@ -256,6 +256,7 @@ impl Server {
db: &Database, db: &Database,
member: Member, member: Member,
intention: RemovalIntention, intention: RemovalIntention,
silent: bool,
) -> Result<()> { ) -> Result<()> {
db.delete_member(&member.id).await?; db.delete_member(&member.id).await?;
@@ -266,6 +267,7 @@ impl Server {
.p(member.id.server) .p(member.id.server)
.await; .await;
if !silent {
if let Some(id) = self.system_messages.as_ref().and_then(|x| match intention { if let Some(id) = self.system_messages.as_ref().and_then(|x| match intention {
RemovalIntention::Leave => x.user_left.as_ref(), RemovalIntention::Leave => x.user_left.as_ref(),
RemovalIntention::Kick => x.user_kicked.as_ref(), RemovalIntention::Kick => x.user_kicked.as_ref(),
@@ -281,6 +283,7 @@ impl Server {
.await .await
.ok(); .ok();
} }
}
Ok(()) Ok(())
} }
@@ -304,7 +307,7 @@ impl Server {
member: Member, member: Member,
reason: Option<String>, reason: Option<String>,
) -> Result<ServerBan> { ) -> Result<ServerBan> {
self.remove_member(db, member.clone(), RemovalIntention::Ban) self.remove_member(db, member.clone(), RemovalIntention::Ban, false)
.await?; .await?;
self.ban_user(db, member.id, reason).await self.ban_user(db, member.id, reason).await
@@ -1,5 +1,3 @@
use std::collections::HashSet;
use bson::{Bson, Document}; use bson::{Bson, Document};
use crate::models::channel::{Channel, FieldsChannel, PartialChannel}; use crate::models::channel::{Channel, FieldsChannel, PartialChannel};
@@ -291,25 +289,6 @@ impl AbstractChannel for MongoDb {
with: "channel", with: "channel",
}) })
} }
async fn check_channels_exist(&self, channels: &HashSet<String>) -> Result<bool> {
let count = channels.len() as u64;
self.col::<Document>(COL)
.count_documents(
doc! {
"_id": {
"$in": channels.iter().cloned().collect::<Vec<String>>()
}
},
None,
)
.await
.map(|x| x == count)
.map_err(|_| Error::DatabaseError {
operation: "count_documents",
with: "channel",
})
}
} }
impl IntoDocumentPath for FieldsChannel { impl IntoDocumentPath for FieldsChannel {
+1 -3
View File
@@ -86,10 +86,8 @@ pub struct Masquerade {
/// Replace the display role colour shown on this message /// Replace the display role colour shown on this message
/// ///
/// Must have `ManageRole` permission to use /// Must have `ManageRole` permission to use
///
/// This can be any valid CSS colour
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
#[validate(length(min = 1, max = 32))] #[validate(length(min = 1, max = 128), regex = "RE_COLOUR")]
pub colour: Option<String>, pub colour: Option<String>,
} }
+6
View File
@@ -32,9 +32,15 @@ pub struct Relationship {
/// Presence status /// Presence status
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)] #[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)]
pub enum Presence { pub enum Presence {
/// User is online
Online, Online,
/// User is not currently available
Idle, Idle,
/// User is focusing / will only receive mentions
Focus,
/// User is busy / will not receive any notifications
Busy, Busy,
/// User appears to be offline
Invisible, Invisible,
} }
@@ -1,5 +1,3 @@
use std::collections::HashSet;
use crate::models::channel::{Channel, FieldsChannel, PartialChannel}; use crate::models::channel::{Channel, FieldsChannel, PartialChannel};
use crate::{OverrideField, Result}; use crate::{OverrideField, Result};
@@ -55,7 +53,4 @@ pub trait AbstractChannel: Sync + Send {
role: &str, role: &str,
permissions: OverrideField, permissions: OverrideField,
) -> Result<()>; ) -> Result<()>;
/// Validate existence of channels
async fn check_channels_exist(&self, channels: &HashSet<String>) -> Result<bool>;
} }