From fdc9fb592d3e39f5a05fde4834f3c461bb103219 Mon Sep 17 00:00:00 2001 From: Nell Date: Fri, 31 Jul 2026 20:56:02 +0200 Subject: [PATCH] init --- src/models/computed_permission.rs | 3 ++ src/repositories/mod.rs | 7 ++- src/repositories/server_tree.rs | 88 +++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/repositories/server_tree.rs diff --git a/src/models/computed_permission.rs b/src/models/computed_permission.rs index 429eb63..f3199f2 100644 --- a/src/models/computed_permission.rs +++ b/src/models/computed_permission.rs @@ -48,6 +48,9 @@ pub struct Model { on_delete = "Cascade" )] pub user: HasOne, + + #[sea_orm(has_many)] + pub computed_permissions: HasMany, } #[async_trait] diff --git a/src/repositories/mod.rs b/src/repositories/mod.rs index f329348..a3fde4f 100644 --- a/src/repositories/mod.rs +++ b/src/repositories/mod.rs @@ -7,8 +7,8 @@ use crate::repositories::message::MessageRepository; use crate::repositories::role::RoleRepository; use crate::repositories::server::ServerRepository; use crate::repositories::server_item_order::ServerItemOrderRepository; +use crate::repositories::server_tree::ServerTreeRepository; use crate::repositories::user::UserRepository; -use event_bus::EventBus; use sea_orm::DatabaseConnection; use std::sync::Arc; @@ -19,6 +19,7 @@ mod message; mod role; mod server; mod server_item_order; +mod server_tree; pub mod types; mod user; @@ -37,6 +38,7 @@ pub struct Repositories { pub user: UserRepository, pub computed_permission: ComputedPermissionRepository, pub server_item_order: ServerItemOrderRepository, + pub server_tree: ServerTreeRepository, } impl Repositories { @@ -68,6 +70,9 @@ impl Repositories { server_item_order: ServerItemOrderRepository { context: context.clone(), }, + server_tree: ServerTreeRepository { + context: context.clone(), + }, } } } diff --git a/src/repositories/server_tree.rs b/src/repositories/server_tree.rs new file mode 100644 index 0000000..df24052 --- /dev/null +++ b/src/repositories/server_tree.rs @@ -0,0 +1,88 @@ +use crate::models::{category, channel, computed_permission, server_item_order}; +use crate::permissions::ChannelPermission; +use crate::repositories::{AnyResult, RepositoryContext}; +use sea_orm::{ColumnTrait, EntityTrait, JoinType, QueryFilter, QuerySelect}; +use std::sync::Arc; +use uuid::Uuid; + +#[derive(Debug, Clone)] +pub struct ChannelWithPermissions { + pub channel: channel::Model, + pub permissions: ChannelPermission, +} + +#[derive(Debug, Clone)] +pub struct ServerTreeData { + pub orders: Vec, + pub categories: Vec, + pub channels: Vec, +} + +#[derive(Clone, Debug)] +pub struct ServerTreeRepository { + pub context: Arc, +} + +impl ServerTreeRepository { + pub async fn get_for_user(&self, server_id: Uuid, user_id: Uuid) -> AnyResult { + let (orders, categories, channel_rows) = tokio::try_join!( + async { + Ok::<_, anyhow::Error>( + server_item_order::Entity::find() + .filter(server_item_order::Column::ServerId.eq(server_id)) + .all(&self.context.db) + .await?, + ) + }, + async { + Ok::<_, anyhow::Error>( + category::Entity::find() + .filter(category::Column::ServerId.eq(server_id)) + .all(&self.context.db) + .await?, + ) + }, + self.find_channels_with_permissions(server_id, user_id), + )?; + + let channels = channel_rows + .into_iter() + .filter_map(|(channel, permission)| { + permission.map(|permission| ChannelWithPermissions { + channel, + permissions: ChannelPermission::from_bits_retain(permission.permissions as u64), + }) + }) + .collect(); + + Ok(ServerTreeData { + orders, + categories, + channels, + }) + } + + async fn find_channels_with_permissions( + &self, + server_id: Uuid, + user_id: Uuid, + ) -> AnyResult)>> { + let rows = channel::Entity::find() + .join( + JoinType::InnerJoin, + channel::Relation::ComputedPermission.def(), + ) + .filter(channel::Column::ServerId.eq(server_id)) + .filter(computed_permission::Column::UserId.eq(user_id)) + .filter(computed_permission::Column::ServerId.eq(server_id)) + .filter( + computed_permission::Column::ScopeType + .eq(computed_permission::PermissionScopeType::Channel), + ) + .select_also(computed_permission::Entity) + .all(&self.context.db) + .await?; + + Ok(rows) + } +}