init
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::models::computed_permission::PermissionScopeType;
|
||||
use crate::models::{channel, channel_user, computed_permission::PermissionScopeType};
|
||||
use crate::permissions::ChannelPermission;
|
||||
use crate::repositories::Repositories;
|
||||
use event_bus::EventBus;
|
||||
@@ -6,6 +6,7 @@ use parking_lot::RwLock;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
|
||||
|
||||
/// In-memory index of the users that can receive events for each channel.
|
||||
#[derive(Debug, Default)]
|
||||
@@ -37,6 +38,24 @@ impl RealtimeRegistry {
|
||||
.insert(permission.resource_id);
|
||||
}
|
||||
|
||||
// Les DM n'utilisent pas les permissions calculées : leur audience est
|
||||
// définie directement par la table d'appartenance channel_user.
|
||||
let dm_channels = channel::Entity::find()
|
||||
.filter(channel::Column::ChannelType.eq(channel::ChannelType::DM))
|
||||
.all(&repositories.channel.context.db)
|
||||
.await?;
|
||||
let dm_ids: Vec<_> = dm_channels.into_iter().map(|item| item.id).collect();
|
||||
if !dm_ids.is_empty() {
|
||||
let members = channel_user::Entity::find()
|
||||
.filter(channel_user::Column::ChannelId.is_in(dm_ids))
|
||||
.all(&repositories.channel.context.db)
|
||||
.await?;
|
||||
for member in members {
|
||||
channel_users.entry(member.channel_id).or_default().insert(member.user_id);
|
||||
user_channels.entry(member.user_id).or_default().insert(member.channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
*self.channel_users.write() = channel_users;
|
||||
*self.user_channels.write() = user_channels;
|
||||
Ok(())
|
||||
@@ -50,6 +69,24 @@ impl RealtimeRegistry {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn set_channel_users(&self, channel_id: Uuid, users: impl IntoIterator<Item = Uuid>) {
|
||||
let users: HashSet<_> = users.into_iter().collect();
|
||||
let old = {
|
||||
let mut by_channel = self.channel_users.write();
|
||||
by_channel.insert(channel_id, users.clone()).unwrap_or_default()
|
||||
};
|
||||
let mut by_user = self.user_channels.write();
|
||||
for user_id in old.difference(&users) {
|
||||
if let Some(channels) = by_user.get_mut(user_id) {
|
||||
channels.remove(&channel_id);
|
||||
if channels.is_empty() { by_user.remove(user_id); }
|
||||
}
|
||||
}
|
||||
for user_id in users {
|
||||
by_user.entry(user_id).or_default().insert(channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_user_channels(&self, user_id: Uuid, channels: impl IntoIterator<Item = Uuid>) {
|
||||
let channels: HashSet<_> = channels.into_iter().collect();
|
||||
let old = self
|
||||
@@ -157,3 +194,27 @@ impl RealtimeRegistry {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::RealtimeRegistry;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn indexes_dm_members_by_channel_and_user() {
|
||||
let registry = RealtimeRegistry::default();
|
||||
let channel_id = Uuid::new_v4();
|
||||
let first = Uuid::new_v4();
|
||||
let second = Uuid::new_v4();
|
||||
|
||||
registry.set_channel_users(channel_id, [first, second]);
|
||||
|
||||
assert_eq!(registry.users_for_channel(channel_id).len(), 2);
|
||||
assert!(registry.user_channels.read().get(&first).unwrap().contains(&channel_id));
|
||||
assert!(registry.user_channels.read().get(&second).unwrap().contains(&channel_id));
|
||||
|
||||
registry.set_channel_users(channel_id, [second]);
|
||||
assert!(!registry.user_channels.read().contains_key(&first));
|
||||
assert!(registry.users_for_channel(channel_id).contains(&second));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user