Merge remote-tracking branch 'origin/main' into livekit

This commit is contained in:
Zomatree
2025-06-02 02:11:51 +01:00
parent 48e0b48ea9
commit ea1c165d80
89 changed files with 1662 additions and 1651 deletions
+26 -1
View File
@@ -3,6 +3,7 @@ mod reference;
use authifier::config::Captcha;
use authifier::config::EmailVerificationConfig;
use authifier::config::PasswordScanning;
use authifier::config::ResolveIp;
use authifier::config::SMTPSettings;
use authifier::config::Shield;
@@ -102,6 +103,13 @@ impl Database {
let config = config().await;
let mut auth_config = authifier::Config {
password_scanning: if config.api.security.easypwned.is_empty() {
Default::default()
} else {
PasswordScanning::EasyPwned {
endpoint: config.api.security.easypwned,
}
},
email_verification: if !config.api.smtp.host.is_empty() {
EmailVerificationConfig::Enabled {
smtp: SMTPSettings {
@@ -118,6 +126,7 @@ impl Database {
),
port: config.api.smtp.port,
use_tls: config.api.smtp.use_tls,
use_starttls: config.api.smtp.use_starttls,
},
expiry: Default::default(),
templates: if config.production {
@@ -134,6 +143,15 @@ impl Database {
url: format!("{}/login/reset/", config.hosts.app),
html: Some(include_str!("../../templates/reset.html").into()),
},
reset_existing: Template {
title: "You already have a Revolt account, reset your password."
.into(),
text: include_str!("../../templates/reset-existing.txt").into(),
url: format!("{}/login/reset/", config.hosts.app),
html: Some(
include_str!("../../templates/reset-existing.html").into(),
),
},
deletion: Template {
title: "Confirm account deletion.".into(),
text: include_str!("../../templates/deletion.txt").into(),
@@ -156,9 +174,16 @@ impl Database {
url: format!("{}/login/reset/", config.hosts.app),
html: None,
},
reset_existing: Template {
title: "Reset your password.".into(),
text: include_str!("../../templates/reset.whitelabel.txt").into(),
url: format!("{}/login/reset/", config.hosts.app),
html: None,
},
deletion: Template {
title: "Confirm account deletion.".into(),
text: include_str!("../../templates/deletion.whitelabel.txt").into(),
text: include_str!("../../templates/deletion.whitelabel.txt")
.into(),
url: format!("{}/delete/", config.hosts.app),
html: None,
},
@@ -4,8 +4,8 @@ use futures::lock::Mutex;
use crate::{
Bot, Channel, ChannelCompositeKey, ChannelUnread, Emoji, File, FileHash, Invite, Member,
MemberCompositeKey, Message, RatelimitEvent, Report, Server, ServerBan, Snapshot, User,
UserSettings, Webhook,
MemberCompositeKey, Message, PolicyChange, RatelimitEvent, Report, Server, ServerBan, Snapshot,
User, UserSettings, Webhook,
};
database_derived!(
@@ -21,6 +21,7 @@ database_derived!(
pub file_hashes: Arc<Mutex<HashMap<String, FileHash>>>,
pub files: Arc<Mutex<HashMap<String, File>>>,
pub messages: Arc<Mutex<HashMap<String, Message>>>,
pub policy_changes: Arc<Mutex<HashMap<String, PolicyChange>>>,
pub ratelimit_events: Arc<Mutex<HashMap<String, RatelimitEvent>>>,
pub user_settings: Arc<Mutex<HashMap<String, UserSettings>>>,
pub users: Arc<Mutex<HashMap<String, User>>>,
+3 -1
View File
@@ -3,7 +3,7 @@ use revolt_result::Error;
use serde::{Deserialize, Serialize};
use revolt_models::v0::{
AppendMessage, Channel, ChannelUnread, ChannelVoiceState, Emoji, FieldsChannel, FieldsMember, FieldsMessage, FieldsRole, FieldsServer, FieldsUser, FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel, PartialMember, PartialMessage, PartialRole, PartialServer, PartialUser, PartialUserVoiceState, PartialWebhook, RemovalIntention, Report, Server, User, UserSettings, UserVoiceState, Webhook
AppendMessage, Channel, ChannelUnread, ChannelVoiceState, Emoji, FieldsChannel, FieldsMember, FieldsMessage, FieldsRole, FieldsServer, FieldsUser, FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel, PartialMember, PartialMessage, PartialRole, PartialServer, PartialUser, PartialUserVoiceState, PartialWebhook, PolicyChange, RemovalIntention, Report, Server, User, UserSettings, UserVoiceState, Webhook
};
use crate::Database;
@@ -62,6 +62,8 @@ pub enum EventV1 {
user_settings: Option<UserSettings>,
#[serde(skip_serializing_if = "Option::is_none")]
channel_unreads: Option<Vec<ChannelUnread>>,
policy_changes: Vec<PolicyChange>,
},
/// Ping response
@@ -64,6 +64,10 @@ pub async fn create_database(db: &MongoDb) {
.await
.expect("Failed to create user_settings collection.");
db.create_collection("policy_changes")
.await
.expect("Failed to create policy_changes collection.");
db.create_collection("safety_reports")
.await
.expect("Failed to create safety_reports collection.");
@@ -5,10 +5,11 @@ use crate::{
bson::{doc, from_bson, from_document, to_document, Bson, DateTime, Document},
options::FindOptions,
},
AbstractChannels, AbstractServers, Channel, Invite, MongoDb, DISCRIMINATOR_SEARCH_SPACE,
AbstractChannels, AbstractServers, Channel, Invite, MongoDb, User, DISCRIMINATOR_SEARCH_SPACE,
};
use bson::oid::ObjectId;
use bson::{oid::ObjectId, to_bson};
use futures::StreamExt;
use iso8601_timestamp::Timestamp;
use rand::seq::SliceRandom;
use revolt_permissions::DEFAULT_WEBHOOK_PERMISSIONS;
use revolt_result::{Error, ErrorType};
@@ -21,7 +22,7 @@ struct MigrationInfo {
revision: i32,
}
pub const LATEST_REVISION: i32 = 33;
pub const LATEST_REVISION: i32 = 43; // MUST BE +1 to last migration
pub async fn migrate_database(db: &MongoDb) {
let migrations = db.col::<Document>("migrations");
@@ -1131,6 +1132,42 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
}
if revision <= 32 {
info!(
"Running migration [revision 32 / 12-05-2025]: (Authifier) Add last_seen to sessions."
);
let db = authifier::Database::MongoDb(authifier::database::MongoDb(db.db()));
db.run_migration(authifier::Migration::M2025_02_20AddLastSeenToSession)
.await
.unwrap();
}
if revision <= 40 {
info!(
"Running migration [revision |> 40 / 30-05-2025]: Set last policy acknowlegement date to now and create policy changes collection."
);
db.db()
.create_collection("policy_changes")
.await
.expect("Failed to create policy_changes collection.");
db.db()
.collection::<User>("users")
.update_many(
doc! {},
doc! {
"$set": {
"last_acknowledged_policy_change": to_bson(&Timestamp::now_utc())
.expect("failed to serialise timestamp")
}
},
)
.await
.expect("failed to update users");
}
if revision <= 41 {
info!("Running migration [revision 32 / 26-01-2025]: Add `is_publishing` and `is_receiving` to members");
db.col::<Document>("server_members")
@@ -1147,7 +1184,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
.expect("Failed to update members");
}
if revision <= 33 {
if revision <= 42 {
info!("Running migration [revision 33 / 29-04-2025]: Convert all `VoiceChannel`'s into `TextChannel` ");
db.col::<Document>("channels")
@@ -1,4 +1,3 @@
use revolt_config::config;
use revolt_result::Result;
use ulid::Ulid;
@@ -142,7 +142,7 @@ mod tests {
..Default::default()
};
db.insert_webhook(&webhook).await.unwrap();
webhook.create(&db).await.unwrap();
let mut updated_webhook = webhook.clone();
updated_webhook
@@ -338,13 +338,10 @@ impl Channel {
db.insert_channel(&channel).await?;
match &channel {
Channel::DirectMessage { .. } => {
let event = EventV1::ChannelCreate(channel.clone().into());
event.clone().private(user_a.id.clone()).await;
event.private(user_b.id.clone()).await;
}
_ => {}
if let Channel::DirectMessage { .. } = &channel {
let event = EventV1::ChannelCreate(channel.clone().into());
event.clone().private(user_a.id.clone()).await;
event.private(user_b.id.clone()).await;
};
Ok(channel)
@@ -28,7 +28,7 @@ auto_derived_partial!(
/// Size of this file (in bytes)
pub size: isize,
},
"PartialFile"
"PartialFileHash"
);
auto_derived!(
@@ -5,7 +5,7 @@ use iso8601_timestamp::Timestamp;
use revolt_config::{config, FeaturesLimits};
use revolt_models::v0::{
self, BulkMessageResponse, DataMessageSend, Embed, MessageAuthor, MessageFlags, MessageSort,
MessageWebhook, PushNotification, ReplyIntent, SendableEmbed, Text
MessageWebhook, PushNotification, ReplyIntent, SendableEmbed, Text,
};
use revolt_permissions::{calculate_channel_permissions, ChannelPermission, PermissionValue};
use revolt_result::{ErrorType, Result};
@@ -288,9 +288,9 @@ impl Message {
.map_err(|_| create_error!(InvalidOperation))?;
// Check the message is not empty
if (data.content.as_ref().map_or(true, |v| v.is_empty()))
&& (data.attachments.as_ref().map_or(true, |v| v.is_empty()))
&& (data.embeds.as_ref().map_or(true, |v| v.is_empty()))
if (data.content.as_ref().is_none_or(|v| v.is_empty()))
&& (data.attachments.as_ref().is_none_or(|v| v.is_empty()))
&& (data.embeds.as_ref().is_none_or(|v| v.is_empty()))
{
return Err(create_error!(EmptyMessage));
}
@@ -384,7 +384,7 @@ impl Message {
mut user_mentions,
mut role_mentions,
mut mentions_everyone,
mut mentions_online
mut mentions_online,
} = message_mentions;
if allow_mass_mentions && server_id.is_some() && !role_mentions.is_empty() {
@@ -492,7 +492,9 @@ impl Message {
let valid_members = db.fetch_members(server.as_str(), &mentions_vec[..]).await;
if let Ok(valid_members) = valid_members {
let valid_mentions = HashSet::<&String, RandomState>::from_iter(valid_members.iter().map(|m| &m.id.user));
let valid_mentions = HashSet::<&String, RandomState>::from_iter(
valid_members.iter().map(|m| &m.id.user),
);
user_mentions.retain(|m| valid_mentions.contains(m)); // quick pass, validate mentions are in the server
@@ -506,7 +508,8 @@ impl Message {
.members_can_see_channel()
.await;
user_mentions.retain(|m| *member_channel_view_perms.get(m).unwrap_or(&false));
user_mentions
.retain(|m| *member_channel_view_perms.get(m).unwrap_or(&false));
}
} else {
revolt_config::capture_error(&valid_members.unwrap_err());
@@ -520,7 +523,9 @@ impl Message {
}
if !user_mentions.is_empty() {
message.mentions.replace(user_mentions.into_iter().collect());
message
.mentions
.replace(user_mentions.into_iter().collect());
}
if !role_mentions.is_empty() {
@@ -654,7 +659,7 @@ impl Message {
pub async fn send(
&mut self,
db: &Database,
amqp: Option<&AMQP>, // this is optional mostly for tests.
_amqp: Option<&AMQP>, // this is optional mostly for tests.
author: MessageAuthor<'_>,
user: Option<v0::User>,
member: Option<v0::Member>,
+3
View File
@@ -8,6 +8,7 @@ mod emojis;
mod file_hashes;
mod files;
mod messages;
mod policy_changes;
mod ratelimit_events;
mod safety_reports;
mod safety_snapshots;
@@ -27,6 +28,7 @@ pub use emojis::*;
pub use file_hashes::*;
pub use files::*;
pub use messages::*;
pub use policy_changes::*;
pub use ratelimit_events::*;
pub use safety_reports::*;
pub use safety_snapshots::*;
@@ -51,6 +53,7 @@ pub trait AbstractDatabase:
+ file_hashes::AbstractAttachmentHashes
+ files::AbstractAttachments
+ messages::AbstractMessages
+ policy_changes::AbstractPolicyChange
+ ratelimit_events::AbstractRatelimitEvents
+ safety_reports::AbstractReport
+ safety_snapshots::AbstractSnapshot
@@ -0,0 +1,5 @@
mod model;
mod ops;
pub use model::*;
pub use ops::*;
@@ -0,0 +1,20 @@
use iso8601_timestamp::Timestamp;
auto_derived!(
/// Platform policy change
pub struct PolicyChange {
/// Unique Id
#[serde(rename = "_id")]
pub id: String,
/// Time at which this policy was created
pub created_time: Timestamp,
/// Time at which this policy is effective
pub effective_time: Timestamp,
/// Message shown to users
pub description: String,
/// URL with details about changes
pub url: String,
}
);
@@ -0,0 +1,15 @@
use revolt_result::Result;
use crate::PolicyChange;
mod mongodb;
mod reference;
#[async_trait]
pub trait AbstractPolicyChange: Sync + Send {
/// Fetch all policy changes
async fn fetch_policy_changes(&self) -> Result<Vec<PolicyChange>>;
/// Acknowledge policy changes
async fn acknowledge_policy_changes(&self, user_id: &str) -> Result<()>;
}
@@ -0,0 +1,46 @@
use bson::to_bson;
use iso8601_timestamp::Timestamp;
use revolt_result::Result;
use crate::MongoDb;
use crate::PolicyChange;
use crate::User;
use super::AbstractPolicyChange;
static COL: &str = "policy_changes";
#[async_trait]
impl AbstractPolicyChange for MongoDb {
/// Fetch all policy changes
async fn fetch_policy_changes(&self) -> Result<Vec<PolicyChange>> {
query!(self, find, COL, doc! {})
}
/// Acknowledge policy changes
async fn acknowledge_policy_changes(&self, user_id: &str) -> Result<()> {
let latest_policy = self
.fetch_policy_changes()
.await?
.into_iter()
.map(|policy| policy.created_time)
.max()
.unwrap_or(Timestamp::UNIX_EPOCH);
self.col::<User>("users")
.update_one(
doc! {
"_id": user_id
},
doc! {
"$set": {
"last_acknowledged_policy_change": to_bson(&latest_policy)
.map_err(|_| create_database_error!("to_bson", "timestamp"))?
}
},
)
.await
.map(|_| ())
.map_err(|_| create_database_error!("update_one", COL))
}
}
@@ -0,0 +1,31 @@
use iso8601_timestamp::Timestamp;
use revolt_result::Result;
use crate::PolicyChange;
use crate::ReferenceDb;
use super::AbstractPolicyChange;
#[async_trait]
impl AbstractPolicyChange for ReferenceDb {
/// Fetch all policy changes
async fn fetch_policy_changes(&self) -> Result<Vec<PolicyChange>> {
let policy_changes = self.policy_changes.lock().await;
Ok(policy_changes.values().cloned().collect())
}
/// Acknowledge policy changes
async fn acknowledge_policy_changes(&self, user_id: &str) -> Result<()> {
let mut users = self.users.lock().await;
let user = users.get_mut(user_id).expect("user doesn't exist");
user.last_acknowledged_policy_change = self
.fetch_policy_changes()
.await?
.into_iter()
.map(|policy| policy.created_time)
.max()
.unwrap_or(Timestamp::UNIX_EPOCH);
Ok(())
}
}
@@ -85,8 +85,8 @@ impl SnapshotContent {
Ok((
SnapshotContent::Message {
message,
prior_context: prior_context.into_iter().map(Into::into).collect(),
leading_context: leading_context.into_iter().map(Into::into).collect(),
prior_context: prior_context.into_iter().collect(),
leading_context: leading_context.into_iter().collect(),
},
files,
))
@@ -13,6 +13,7 @@ auto_derived!(
}
);
#[allow(clippy::disallowed_methods)]
impl ServerBan {
/// Create ban
pub async fn create(
@@ -180,7 +180,7 @@ impl Member {
}
/// Update member data
pub async fn update<'a>(
pub async fn update(
&mut self,
db: &Database,
partial: PartialMember,
@@ -285,7 +285,7 @@ impl Role {
}
/// Update server data
pub async fn update<'a>(
pub async fn update(
&mut self,
db: &Database,
server_id: &str,
+12 -11
View File
@@ -9,7 +9,7 @@ use once_cell::sync::Lazy;
use rand::seq::SliceRandom;
use redis_kiss::{get_connection, AsyncCommands};
use revolt_config::{config, FeaturesLimits};
use revolt_models::v0::{self, UserFlags, UserBadges};
use revolt_models::v0::{self, UserBadges, UserFlags};
use revolt_presence::filter_online;
use revolt_result::{create_error, Result};
use serde_json::json;
@@ -58,6 +58,8 @@ auto_derived_partial!(
/// Time until user is unsuspended
#[serde(skip_serializing_if = "Option::is_none")]
pub suspended_until: Option<Timestamp>,
/// Last acknowledged policy change
pub last_acknowledged_policy_change: Timestamp,
},
"PartialUser"
);
@@ -179,6 +181,7 @@ impl Default for User {
privileged: Default::default(),
bot: Default::default(),
suspended_until: Default::default(),
last_acknowledged_policy_change: Timestamp::UNIX_EPOCH,
}
}
}
@@ -201,6 +204,7 @@ impl User {
id: account_id.into().unwrap_or_else(|| Ulid::new().to_string()),
discriminator: User::find_discriminator(db, &username, None).await?,
username,
last_acknowledged_policy_change: Timestamp::now_utc(),
..Default::default()
};
@@ -350,16 +354,13 @@ impl User {
) -> Result<Vec<v0::User>> {
let online_ids = filter_online(ids).await;
Ok(join_all(
db
.fetch_users(ids)
.await?
.into_iter()
.map(|user| async {
Ok(
join_all(db.fetch_users(ids).await?.into_iter().map(|user| async {
let is_online = online_ids.contains(&user.id);
user.into_known(perspective, is_online).await
})
).await)
}))
.await,
)
}
/// Find a free discriminator for a given username
@@ -653,7 +654,7 @@ impl User {
}
/// Update user data
pub async fn update<'a>(
pub async fn update(
&mut self,
db: &Database,
partial: PartialUser,
@@ -831,7 +832,7 @@ impl User {
if let Some(cutoff) = config.api.users.early_adopter_cutoff {
if Ulid::from_string(&self.id).unwrap().timestamp_ms() < cutoff {
return badges + UserBadges::EarlyAdopter as u32
return badges + UserBadges::EarlyAdopter as u32;
};
};
@@ -6,7 +6,7 @@ use revolt_rocket_okapi::{
use crate::User;
impl<'r> OpenApiFromRequest<'r> for User {
impl OpenApiFromRequest<'_> for User {
fn from_request_input(
_gen: &mut OpenApiGenerator,
_name: String,
+31 -21
View File
@@ -3,8 +3,8 @@ use crate::{Database, Message, AMQP};
use deadqueue::limited::Queue;
use once_cell::sync::Lazy;
use revolt_config::capture_message;
use revolt_models::v0::PushNotification;
use rocket::form::validate::Contains;
use std::{
collections::{HashMap, HashSet},
time::Duration,
@@ -65,6 +65,7 @@ pub async fn queue_ack(channel: String, user: String, event: AckEvent) {
);
}
/// Do not add more than one message per event.
pub async fn queue_message(channel: String, event: AckEvent) {
Q.try_push(Data {
channel,
@@ -114,7 +115,7 @@ pub async fn handle_ack_event(
}
AckEvent::ProcessMessage { messages } => {
let mut users: HashSet<&String> = HashSet::new();
debug!(
info!(
"Processing {} messages from channel {}",
messages.len(),
messages[0].1.channel
@@ -125,7 +126,7 @@ pub async fn handle_ack_event(
users.extend(recipents.iter());
});
debug!("Found {} users to notify.", users.len());
info!("Found {} users to notify.", users.len());
for user in users {
let message_ids: Vec<String> = messages
@@ -143,7 +144,7 @@ pub async fn handle_ack_event(
db.add_mention_to_unread(channel, user, &message_ids)
.await?;
}
debug!("Added {} mentions for user {}", message_ids.len(), &user);
info!("Added {} mentions for user {}", message_ids.len(), &user);
}
let mut mass_mentions = vec![];
@@ -232,7 +233,7 @@ pub async fn worker(db: Database, amqp: AMQP) {
revolt_config::capture_error(&err);
error!("{err:?} for {event:?}. ({user:?}, {channel})");
} else {
debug!("User {user:?} ack in {channel} with {event:?}");
info!("User {user:?} ack in {channel} with {event:?}");
}
}
}
@@ -247,6 +248,8 @@ pub async fn worker(db: Database, amqp: AMQP) {
mut event,
}) = Q.try_pop()
{
info!("Took next ack from queue, now {} remaining", Q.len());
let key: (Option<String>, String, u8) = (
user,
channel,
@@ -261,24 +264,31 @@ pub async fn worker(db: Database, amqp: AMQP) {
if let AckEvent::ProcessMessage { messages: existing } =
&mut task.data.event
{
// add the new message to the list of messages to be processed.
existing.append(new_data);
if let Some(new_event) = new_data.pop() {
// if the message contains a mass mention, do not delay it any further.
if new_event.1.contains_mass_push_mention() {
// add the new message to the list of messages to be processed.
existing.push(new_event);
task.run_immediately();
continue;
}
// if the message contains a mass mention, do not delay it any further.
if new_data[0].1.contains_mass_push_mention() {
task.run_immediately();
continue;
}
existing.push(new_event);
// put a cap on the amount of messages that can be queued, for particularly active channels
if (existing.length() as u16)
< revolt_config::config()
.await
.features
.advanced
.process_message_delay_limit
{
task.delay();
// put a cap on the amount of messages that can be queued, for particularly active channels
if (existing.length() as u16)
< revolt_config::config()
.await
.features
.advanced
.process_message_delay_limit
{
task.delay();
}
} else {
let err_msg = format!("Got zero-length message event: {event:?}");
capture_message(&err_msg, revolt_config::Level::Warning);
info!("{err_msg}")
}
} else {
panic!("Somehow got an ack message in the add mention arm");
+16 -3
View File
@@ -1,7 +1,8 @@
use iso8601_timestamp::Timestamp;
use revolt_models::v0::*;
use revolt_permissions::{calculate_user_permissions, UserPermission};
use crate::{util::permissions::DatabasePermissionQuery, Database, FileUsedFor};
use crate::{util::permissions::DatabasePermissionQuery, Database};
impl crate::Bot {
pub fn into_public_bot(self, user: crate::User) -> PublicBot {
@@ -496,7 +497,7 @@ impl crate::Message {
reactions: self.reactions,
interactions: self.interactions.into(),
masquerade: self.masquerade.map(Into::into),
flags: self.flags.map(|flags| flags as u32).unwrap_or_default(),
flags: self.flags.unwrap_or_default(),
pinned: self.pinned,
}
}
@@ -525,7 +526,7 @@ impl From<crate::PartialMessage> for PartialMessage {
reactions: value.reactions,
interactions: value.interactions.map(Into::into),
masquerade: value.masquerade.map(Into::into),
flags: value.flags.map(|flags| flags as u32),
flags: value.flags,
pinned: value.pinned,
}
}
@@ -606,6 +607,17 @@ impl From<Masquerade> for crate::Masquerade {
}
}
impl From<crate::PolicyChange> for PolicyChange {
fn from(value: crate::PolicyChange) -> Self {
PolicyChange {
created_time: value.created_time,
effective_time: value.effective_time,
description: value.description,
url: value.url,
}
}
}
impl From<crate::Report> for Report {
fn from(value: crate::Report) -> Self {
Report {
@@ -1209,6 +1221,7 @@ impl From<User> for crate::User {
privileged: value.privileged,
bot: value.bot.map(Into::into),
suspended_until: None,
last_acknowledged_policy_change: Timestamp::UNIX_EPOCH,
}
}
}
@@ -87,7 +87,7 @@ impl<'z> BulkDatabasePermissionQuery<'z> {
}
}
pub fn channel(self, channel: &'z Channel) -> BulkDatabasePermissionQuery {
pub fn channel(self, channel: &'z Channel) -> BulkDatabasePermissionQuery<'z> {
BulkDatabasePermissionQuery {
channel: Some(channel.clone()),
..self
@@ -109,7 +109,7 @@ impl<'z> BulkDatabasePermissionQuery<'z> {
}
}
pub fn members(self, members: &'z [Member]) -> BulkDatabasePermissionQuery {
pub fn members(self, members: &'z [Member]) -> BulkDatabasePermissionQuery<'z> {
BulkDatabasePermissionQuery {
members: Some(members.to_owned()),
cached_member_perms: None,
@@ -120,7 +120,7 @@ impl<'z> BulkDatabasePermissionQuery<'z> {
}
}
pub fn users(self, users: &'z [User]) -> BulkDatabasePermissionQuery {
pub fn users(self, users: &'z [User]) -> BulkDatabasePermissionQuery<'z> {
BulkDatabasePermissionQuery {
users: Some(users.to_owned()),
cached_member_perms: None,
+12 -14
View File
@@ -308,16 +308,14 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
/// Are we a recipient of this channel?
async fn are_we_part_of_the_channel(&mut self) -> bool {
if let Some(channel) = &self.channel {
match channel {
Cow::Borrowed(Channel::DirectMessage { recipients, .. })
| Cow::Owned(Channel::DirectMessage { recipients, .. })
| Cow::Borrowed(Channel::Group { recipients, .. })
| Cow::Owned(Channel::Group { recipients, .. }) => {
recipients.contains(&self.perspective.id)
}
_ => false,
}
if let Some(
Cow::Borrowed(Channel::DirectMessage { recipients, .. })
| Cow::Owned(Channel::DirectMessage { recipients, .. })
| Cow::Borrowed(Channel::Group { recipients, .. })
| Cow::Owned(Channel::Group { recipients, .. }),
) = &self.channel
{
recipients.contains(&self.perspective.id)
} else {
false
}
@@ -424,7 +422,7 @@ impl<'a> DatabasePermissionQuery<'a> {
}
/// Use user
pub fn user(self, user: &'a User) -> DatabasePermissionQuery {
pub fn user(self, user: &'a User) -> DatabasePermissionQuery<'a> {
DatabasePermissionQuery {
user: Some(Cow::Borrowed(user)),
..self
@@ -432,7 +430,7 @@ impl<'a> DatabasePermissionQuery<'a> {
}
/// Use channel
pub fn channel(self, channel: &'a Channel) -> DatabasePermissionQuery {
pub fn channel(self, channel: &'a Channel) -> DatabasePermissionQuery<'a> {
DatabasePermissionQuery {
channel: Some(Cow::Borrowed(channel)),
..self
@@ -440,7 +438,7 @@ impl<'a> DatabasePermissionQuery<'a> {
}
/// Use server
pub fn server(self, server: &'a Server) -> DatabasePermissionQuery {
pub fn server(self, server: &'a Server) -> DatabasePermissionQuery<'a> {
DatabasePermissionQuery {
server: Some(Cow::Borrowed(server)),
..self
@@ -448,7 +446,7 @@ impl<'a> DatabasePermissionQuery<'a> {
}
/// Use member
pub fn member(self, member: &'a Member) -> DatabasePermissionQuery {
pub fn member(self, member: &'a Member) -> DatabasePermissionQuery<'a> {
DatabasePermissionQuery {
member: Some(Cow::Borrowed(member)),
..self