From 825db3a2925a3dd1d6994602b4b62649276100e2 Mon Sep 17 00:00:00 2001 From: Nell Date: Sat, 11 Jul 2026 11:21:09 +0200 Subject: [PATCH] init --- .../src/m20220101_000001_create_table.rs | 162 +++++++++++------- src/models/channel.rs | 2 - src/models/channel_user.rs | 1 - src/models/computed_permission.rs | 38 ++++ src/models/group_member.rs | 17 ++ src/models/mod.rs | 2 + src/models/server.rs | 21 +-- src/models/server_user.rs | 7 - src/models/user_permission.rs | 51 ++++++ 9 files changed, 207 insertions(+), 94 deletions(-) create mode 100644 src/models/computed_permission.rs create mode 100644 src/models/user_permission.rs diff --git a/migration/src/m20220101_000001_create_table.rs b/migration/src/m20220101_000001_create_table.rs index a75e1db..26a2524 100644 --- a/migration/src/m20220101_000001_create_table.rs +++ b/migration/src/m20220101_000001_create_table.rs @@ -27,30 +27,13 @@ impl MigrationTrait for Migration { .not_null() .default(Expr::current_timestamp()), ) - .col( - ColumnDef::new(Alias::new("default_server_permissions")) - .big_integer() - .not_null() - .default(0), - ) - .col( - ColumnDef::new(Alias::new("default_channel_permissions")) - .big_integer() - .not_null() - .default(0), - ) - .col( - ColumnDef::new(Alias::new("default_voice_permissions")) - .big_integer() - .not_null() - .default(0), - ) .col( ColumnDef::new(Alias::new("is_default")) .boolean() .not_null() .default(false), ) + .col(ColumnDef::new(Alias::new("owner_id")).uuid().not_null()) .to_owned(), ) .await?; @@ -125,16 +108,6 @@ impl MigrationTrait for Migration { .integer() .not_null(), ) - .col( - ColumnDef::new(Alias::new("default_channel_permissions")) - .big_integer() - .null(), - ) - .col( - ColumnDef::new(Alias::new("default_voice_permissions")) - .big_integer() - .null(), - ) .col(ColumnDef::new(Alias::new("name")).string().null()) .col( ColumnDef::new(Alias::new("created_at")) @@ -327,36 +300,6 @@ impl MigrationTrait for Migration { .not_null() .default(Expr::current_timestamp()), ) - .col( - ColumnDef::new(Alias::new("is_admin")) - .boolean() - .not_null() - .default(false), - ) - .col( - ColumnDef::new(Alias::new("is_owner")) - .boolean() - .not_null() - .default(false), - ) - .col( - ColumnDef::new(Alias::new("server_permissions")) - .big_integer() - .not_null() - .default(0), - ) - .col( - ColumnDef::new(Alias::new("channel_permissions")) - .big_integer() - .not_null() - .default(0), - ) - .col( - ColumnDef::new(Alias::new("voice_permissions")) - .big_integer() - .not_null() - .default(0), - ) // Indexes créés après .foreign_key( ForeignKey::create() @@ -390,12 +333,6 @@ impl MigrationTrait for Migration { ) .col(ColumnDef::new(Alias::new("channel_id")).uuid().not_null()) .col(ColumnDef::new(Alias::new("user_id")).uuid().not_null()) - .col( - ColumnDef::new(Alias::new("role")) - .string() - .not_null() - .default("member".to_owned()), - ) .col( ColumnDef::new(Alias::new("joined_at")) .timestamp_with_time_zone() @@ -636,6 +573,8 @@ impl MigrationTrait for Migration { .if_not_exists() .col(ColumnDef::new("group_id").uuid().not_null()) .col(ColumnDef::new("user_id").uuid().not_null()) + .col(ColumnDef::new("scope_type").integer().not_null()) + .col(ColumnDef::new("scope_id").uuid().not_null()) .primary_key( Index::create() .col(Alias::new("group_id")) @@ -681,6 +620,101 @@ impl MigrationTrait for Migration { ) .await?; + // Create table `user_permission` + manager + .create_table( + Table::create() + .table(Alias::new("user_permission")) + .if_not_exists() + .col(ColumnDef::new("id").uuid().primary_key().not_null()) + .col(ColumnDef::new("user_id").uuid().not_null()) + .col(ColumnDef::new("server_id").uuid().not_null()) + .col(ColumnDef::new("scope_type").integer().not_null()) + .col(ColumnDef::new("scope_id").uuid().not_null()) + .col( + ColumnDef::new(Alias::new("server_permissions")) + .big_integer() + .not_null() + .default(0), + ) + .col( + ColumnDef::new(Alias::new("channel_permissions")) + .big_integer() + .not_null() + .default(0), + ) + .col( + ColumnDef::new(Alias::new("voice_permissions")) + .big_integer() + .not_null() + .default(0), + ) + .col( + ColumnDef::new("created_at") + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .foreign_key( + ForeignKey::create() + .name("fk_user_permission_user") + .from(Alias::new("user_permission"), Alias::new("user_id")) + .to(Alias::new("user"), Alias::new("id")) + .on_delete(ForeignKeyAction::Cascade), + ) + .foreign_key( + ForeignKey::create() + .name("fk_user_permission_server") + .from(Alias::new("user_permission"), Alias::new("server_id")) + .to(Alias::new("server"), Alias::new("id")) + .on_delete(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await?; + + // Create CACHE table `computed_permission` + manager + .create_table( + Table::create() + .table(Alias::new("computed_permission")) + .if_not_exists() + .col(ColumnDef::new("user_id").uuid().not_null()) + .col(ColumnDef::new("resource_id").uuid().not_null()) + .col( + ColumnDef::new(Alias::new("server_permissions")) + .big_integer() + .not_null() + .default(0), + ) + .col( + ColumnDef::new(Alias::new("channel_permissions")) + .big_integer() + .not_null() + .default(0), + ) + .col( + ColumnDef::new(Alias::new("voice_permissions")) + .big_integer() + .not_null() + .default(0), + ) + .primary_key( + Index::create() + .col(Alias::new("user_id")) + .col(Alias::new("resource_id")), + ) + .foreign_key( + ForeignKey::create() + .name("fk_computed_permission_user") + .from(Alias::new("computed_permission"), Alias::new("user_id")) + .to(Alias::new("user"), Alias::new("id")) + .on_delete(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await?; + Ok(()) } diff --git a/src/models/channel.rs b/src/models/channel.rs index 570e547..063391c 100644 --- a/src/models/channel.rs +++ b/src/models/channel.rs @@ -32,8 +32,6 @@ pub struct Model { pub name: Option, pub created_at: DateTimeUtc, pub updated_at: DateTimeUtc, - pub default_channel_permissions: Option, - pub default_voice_permissions: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/models/channel_user.rs b/src/models/channel_user.rs index a557580..22a44da 100644 --- a/src/models/channel_user.rs +++ b/src/models/channel_user.rs @@ -12,7 +12,6 @@ pub struct Model { pub channel_id: Uuid, pub user_id: Uuid, pub role: String, - pub permissions: u64, pub joined_at: DateTimeUtc, } diff --git a/src/models/computed_permission.rs b/src/models/computed_permission.rs new file mode 100644 index 0000000..019f8c6 --- /dev/null +++ b/src/models/computed_permission.rs @@ -0,0 +1,38 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "computed_permission")] +pub struct Model { + /// L'utilisateur à qui appartiennent ces permissions + #[sea_orm(primary_key, auto_increment = false)] + pub user_id: Uuid, + + /// L'ID de la ressource (soit un Uuid de Channel, soit l'Uuid du Server) + #[sea_orm(primary_key, auto_increment = false)] + pub resource_id: Uuid, + + /// Cache des permissions serveur (stocké en i64 pour SQL, utilisé en u64) + pub server_permissions: i64, + pub channel_permissions: i64, + pub voice_permissions: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/models/group_member.rs b/src/models/group_member.rs index 847c178..8e956b8 100644 --- a/src/models/group_member.rs +++ b/src/models/group_member.rs @@ -1,6 +1,21 @@ //! `SeaORM` Entity. use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; + +#[derive( + Debug, Clone, Copy, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize, ToSchema, +)] +#[sea_orm(rs_type = "i32", db_type = "Integer")] +pub enum PermissionScopeType { + #[sea_orm(num_value = 0)] + Server, + #[sea_orm(num_value = 1)] + Category, + #[sea_orm(num_value = 2)] + Channel, +} #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "group_member")] @@ -9,6 +24,8 @@ pub struct Model { pub group_id: Uuid, #[sea_orm(primary_key, auto_increment = false)] pub user_id: Uuid, + pub scope_type: PermissionScopeType, + pub scope_id: Uuid, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/models/mod.rs b/src/models/mod.rs index 55cb265..1750f15 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -6,9 +6,11 @@ pub mod attachment; pub mod category; pub mod channel; pub mod channel_user; +mod computed_permission; pub mod group; pub mod group_member; pub mod message; pub mod server; pub mod server_user; pub mod user; +mod user_permission; diff --git a/src/models/server.rs b/src/models/server.rs index 16474fa..61f8e86 100644 --- a/src/models/server.rs +++ b/src/models/server.rs @@ -1,6 +1,5 @@ //! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.19 -use crate::permissions::{ChannelPermission, PermissionSet, ServerPermission, VoicePermission}; use sea_orm::entity::prelude::*; use sea_orm::prelude::async_trait::async_trait; use sea_orm::Set; @@ -15,11 +14,7 @@ pub struct Model { pub created_at: DateTimeUtc, pub updated_at: DateTimeUtc, pub is_default: bool, - - /// Permissions serveur par défaut (stockées en i64, lues en u64) - pub default_server_permissions: i64, - pub default_channel_permissions: i64, - pub default_voice_permissions: i64, + pub owned_id: Uuid, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -53,24 +48,10 @@ impl Related for Entity { #[async_trait] impl ActiveModelBehavior for ActiveModel { fn new() -> Self { - let default_perm = PermissionSet::DEFAULT; Self { id: Set(Uuid::new_v4()), is_default: Set(false), - default_server_permissions: Set(default_perm.server.bits() as i64), - default_channel_permissions: Set(default_perm.channel.bits() as i64), - default_voice_permissions: Set(default_perm.voice.bits() as i64), ..ActiveModelTrait::default() } } } - -impl Model { - pub fn default_permissions(&self) -> PermissionSet { - PermissionSet { - server: ServerPermission::from_bits_truncate(self.default_server_permissions as u64), - channel: ChannelPermission::from_bits_truncate(self.default_channel_permissions as u64), - voice: VoicePermission::from_bits_truncate(self.default_voice_permissions as u64), - } - } -} diff --git a/src/models/server_user.rs b/src/models/server_user.rs index 21a661d..cd6b194 100644 --- a/src/models/server_user.rs +++ b/src/models/server_user.rs @@ -14,13 +14,6 @@ pub struct Model { pub username: Option, pub joined_at: DateTimeUtc, pub updated_at: DateTimeUtc, - pub is_admin: bool, - pub is_owner: bool, - - /// Permissions serveur par défaut (stockées en i64, lues en u64) - pub server_permissions: i64, - pub channel_permissions: i64, - pub voice_permissions: i64, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/models/user_permission.rs b/src/models/user_permission.rs new file mode 100644 index 0000000..61fdb61 --- /dev/null +++ b/src/models/user_permission.rs @@ -0,0 +1,51 @@ +use super::group_member::PermissionScopeType; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "user_permission")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Uuid, + pub user_id: Uuid, + pub server_id: Uuid, + pub scope_type: PermissionScopeType, + pub scope_id: Uuid, + pub server_permissions: i64, + pub channel_permissions: i64, + pub voice_permissions: i64, + pub created_at: DateTimeUtc, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm( + belongs_to = "super::server::Entity", + from = "Column::ServerId", + to = "super::server::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Server, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Server.def() + } +} + +impl ActiveModelBehavior for ActiveModel {}