diff --git a/migration/src/m20220101_000001_create_table.rs b/migration/src/m20220101_000001_create_table.rs index 26a2524..c44ce10 100644 --- a/migration/src/m20220101_000001_create_table.rs +++ b/migration/src/m20220101_000001_create_table.rs @@ -6,141 +6,10 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - // Create table `server` - manager - .create_table( - Table::create() - .table(Alias::new("server")) - .if_not_exists() - .col(ColumnDef::new("id").uuid().primary_key().not_null()) - .col(ColumnDef::new("name").string().not_null()) - .col(ColumnDef::new("password").string().null()) - .col( - ColumnDef::new(Alias::new("created_at")) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .col( - ColumnDef::new(Alias::new("updated_at")) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .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?; + // --------------------------------------------------------------------- + // Tables principales + // --------------------------------------------------------------------- - // Create table `category` - manager - .create_table( - Table::create() - .table(Alias::new("category")) - .if_not_exists() - .col( - ColumnDef::new(Alias::new("id")) - .uuid() - .not_null() - .primary_key(), - ) - .col(ColumnDef::new(Alias::new("server_id")).uuid().not_null()) - .col(ColumnDef::new(Alias::new("name")).string().not_null()) - .col( - ColumnDef::new(Alias::new("position")) - .integer() - .not_null() - .default(0), - ) - .col( - ColumnDef::new(Alias::new("created_at")) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .col( - ColumnDef::new(Alias::new("updated_at")) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - // L'index sera créé après via manager.create_index - .foreign_key( - ForeignKey::create() - .name("fk_category_server") - .from(Alias::new("category"), Alias::new("server_id")) - .to(Alias::new("server"), Alias::new("id")) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade), - ) - .to_owned(), - ) - .await?; - - // Create table `channel` - manager - .create_table( - Table::create() - .table(Alias::new("channel")) - .if_not_exists() - .col( - ColumnDef::new(Alias::new("id")) - .uuid() - .not_null() - .primary_key(), - ) - .col(ColumnDef::new(Alias::new("server_id")).uuid().null()) - .col(ColumnDef::new(Alias::new("category_id")).uuid().null()) - .col( - ColumnDef::new(Alias::new("position")) - .integer() - .not_null() - .default(0), - ) - .col( - ColumnDef::new(Alias::new("channel_type")) - .integer() - .not_null(), - ) - .col(ColumnDef::new(Alias::new("name")).string().null()) - .col( - ColumnDef::new(Alias::new("created_at")) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .col( - ColumnDef::new(Alias::new("updated_at")) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - // Indexes créés après - .foreign_key( - ForeignKey::create() - .name("fk_channel_server") - .from(Alias::new("channel"), Alias::new("server_id")) - .to(Alias::new("server"), Alias::new("id")) - .on_delete(ForeignKeyAction::Cascade), - ) - .foreign_key( - ForeignKey::create() - .name("fk_channel_category") - .from(Alias::new("channel"), Alias::new("category_id")) - .to(Alias::new("category"), Alias::new("id")) - .on_delete(ForeignKeyAction::SetNull), - ) - .to_owned(), - ) - .await?; - - // Create table `user` manager .create_table( Table::create() @@ -182,7 +51,144 @@ impl MigrationTrait for Migration { ) .await?; - // Create table `message` + manager + .create_table( + Table::create() + .table(Alias::new("server")) + .if_not_exists() + .col( + ColumnDef::new(Alias::new("id")) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(Alias::new("name")).string().not_null()) + .col(ColumnDef::new(Alias::new("password")).string().null()) + .col( + ColumnDef::new(Alias::new("created_at")) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .col( + ColumnDef::new(Alias::new("updated_at")) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .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?; + + manager + .create_table( + Table::create() + .table(Alias::new("category")) + .if_not_exists() + .col( + ColumnDef::new(Alias::new("id")) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(Alias::new("server_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("name")).string().not_null()) + .col( + ColumnDef::new(Alias::new("position")) + .integer() + .not_null() + .default(0), + ) + .col( + ColumnDef::new(Alias::new("created_at")) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .col( + ColumnDef::new(Alias::new("updated_at")) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .foreign_key( + ForeignKey::create() + .name("fk_category_server") + .from(Alias::new("category"), Alias::new("server_id")) + .to(Alias::new("server"), Alias::new("id")) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await?; + + manager + .create_table( + Table::create() + .table(Alias::new("channel")) + .if_not_exists() + .col( + ColumnDef::new(Alias::new("id")) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(Alias::new("server_id")).uuid().null()) + .col(ColumnDef::new(Alias::new("category_id")).uuid().null()) + .col( + ColumnDef::new(Alias::new("position")) + .integer() + .not_null() + .default(0), + ) + .col( + ColumnDef::new(Alias::new("channel_type")) + .integer() + .not_null(), + ) + .col(ColumnDef::new(Alias::new("name")).string().null()) + .col( + ColumnDef::new(Alias::new("created_at")) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .col( + ColumnDef::new(Alias::new("updated_at")) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .foreign_key( + ForeignKey::create() + .name("fk_channel_server") + .from(Alias::new("channel"), Alias::new("server_id")) + .to(Alias::new("server"), Alias::new("id")) + .on_delete(ForeignKeyAction::Cascade), + ) + .foreign_key( + ForeignKey::create() + .name("fk_channel_category") + .from(Alias::new("channel"), Alias::new("category_id")) + .to(Alias::new("category"), Alias::new("id")) + .on_delete(ForeignKeyAction::SetNull), + ) + .to_owned(), + ) + .await?; + + // --------------------------------------------------------------------- + // Contenu et relations utilisateurs + // --------------------------------------------------------------------- + manager .create_table( Table::create() @@ -209,7 +215,6 @@ impl MigrationTrait for Migration { .null(), ) .col(ColumnDef::new(Alias::new("reply_to_id")).uuid().null()) - // Indexes créés après .foreign_key( ForeignKey::create() .name("fk_message_channel") @@ -235,7 +240,6 @@ impl MigrationTrait for Migration { ) .await?; - // Create table `attachment` manager .create_table( Table::create() @@ -261,7 +265,6 @@ impl MigrationTrait for Migration { .not_null() .default(Expr::current_timestamp()), ) - // Index créé après .foreign_key( ForeignKey::create() .name("fk_attachment_message") @@ -273,7 +276,6 @@ impl MigrationTrait for Migration { ) .await?; - // Create M2M table `server_user` manager .create_table( Table::create() @@ -300,7 +302,6 @@ impl MigrationTrait for Migration { .not_null() .default(Expr::current_timestamp()), ) - // Indexes créés après .foreign_key( ForeignKey::create() .name("fk_server_user_server") @@ -319,7 +320,6 @@ impl MigrationTrait for Migration { ) .await?; - // Create M2M table `channel_user` manager .create_table( Table::create() @@ -333,13 +333,18 @@ 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"), + ) .col( ColumnDef::new(Alias::new("joined_at")) .timestamp_with_time_zone() .not_null() .default(Expr::current_timestamp()), ) - // Indexes créés après .foreign_key( ForeignKey::create() .name("fk_channel_user_channel") @@ -358,202 +363,35 @@ impl MigrationTrait for Migration { ) .await?; - // -------------------------------------------------------------------- - // Création des INDEX après les tables - // -------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Groupes et attributions + // --------------------------------------------------------------------- - // category(server_id) - manager - .create_index( - Index::create() - .name("idx_category_server_id") - .table(Alias::new("category")) - .col(Alias::new("server_id")) - .to_owned(), - ) - .await?; - - // channel(server_id) - manager - .create_index( - Index::create() - .name("idx_channel_server_id") - .table(Alias::new("channel")) - .col(Alias::new("server_id")) - .to_owned(), - ) - .await?; - - // channel(category_id) - manager - .create_index( - Index::create() - .name("idx_channel_category_id") - .table(Alias::new("channel")) - .col(Alias::new("category_id")) - .to_owned(), - ) - .await?; - - // message(channel_id) - manager - .create_index( - Index::create() - .name("idx_message_channel_id") - .table(Alias::new("message")) - .col(Alias::new("channel_id")) - .to_owned(), - ) - .await?; - - // message(user_id) - manager - .create_index( - Index::create() - .name("idx_message_user_id") - .table(Alias::new("message")) - .col(Alias::new("user_id")) - .to_owned(), - ) - .await?; - - // message(reply_to_id) - manager - .create_index( - Index::create() - .name("idx_message_reply_to_id") - .table(Alias::new("message")) - .col(Alias::new("reply_to_id")) - .to_owned(), - ) - .await?; - - // attachment(message_id) - manager - .create_index( - Index::create() - .name("idx_attachment_message_id") - .table(Alias::new("attachment")) - .col(Alias::new("message_id")) - .to_owned(), - ) - .await?; - - // server_user(server_id) - manager - .create_index( - Index::create() - .name("idx_server_user_server_id") - .table(Alias::new("server_user")) - .col(Alias::new("server_id")) - .to_owned(), - ) - .await?; - - // server_user(user_id) - manager - .create_index( - Index::create() - .name("idx_server_user_user_id") - .table(Alias::new("server_user")) - .col(Alias::new("user_id")) - .to_owned(), - ) - .await?; - - // unique (server_id, user_id) - manager - .create_index( - Index::create() - .name("uk_server_user_server_user") - .table(Alias::new("server_user")) - .col(Alias::new("server_id")) - .col(Alias::new("user_id")) - .unique() - .to_owned(), - ) - .await?; - - // channel_user(channel_id) - manager - .create_index( - Index::create() - .name("idx_channel_user_channel_id") - .table(Alias::new("channel_user")) - .col(Alias::new("channel_id")) - .to_owned(), - ) - .await?; - - // channel_user(user_id) - manager - .create_index( - Index::create() - .name("idx_channel_user_user_id") - .table(Alias::new("channel_user")) - .col(Alias::new("user_id")) - .to_owned(), - ) - .await?; - - // unique (channel_id, user_id) - manager - .create_index( - Index::create() - .name("uk_channel_user_channel_user") - .table(Alias::new("channel_user")) - .col(Alias::new("channel_id")) - .col(Alias::new("user_id")) - .unique() - .to_owned(), - ) - .await?; - - // Create table `group` manager .create_table( Table::create() .table(Alias::new("group")) .if_not_exists() - .col(ColumnDef::new("id").uuid().primary_key().not_null()) - .col(ColumnDef::new("server_id").uuid().not_null()) - .col(ColumnDef::new("name").string().not_null()) .col( - ColumnDef::new(Alias::new("server_permissions")) - .big_integer() + ColumnDef::new(Alias::new("id")) + .uuid() .not_null() - .default(0), + .primary_key(), ) + .col(ColumnDef::new(Alias::new("server_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("name")).string().not_null()) .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("is_default") + ColumnDef::new(Alias::new("is_default")) .boolean() .not_null() .default(false), ) .col( - ColumnDef::new("created_at") + ColumnDef::new(Alias::new("created_at")) .timestamp_with_time_zone() .not_null() .default(Expr::current_timestamp()), ) - .col( - ColumnDef::new("edited_at") - .timestamp_with_time_zone() - .null() - .default(Expr::current_timestamp()), - ) .foreign_key( ForeignKey::create() .name("fk_group_server") @@ -565,16 +403,13 @@ impl MigrationTrait for Migration { ) .await?; - // Create table `group_member` manager .create_table( Table::create() .table(Alias::new("group_member")) .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()) + .col(ColumnDef::new(Alias::new("group_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("user_id")).uuid().not_null()) .primary_key( Index::create() .col(Alias::new("group_id")) @@ -598,39 +433,29 @@ impl MigrationTrait for Migration { ) .await?; - // Index: idx_group_server_id - manager - .create_index( - Index::create() - .name("idx_group_server_id") - .table(Alias::new("group")) - .col(Alias::new("server_id")) - .to_owned(), - ) - .await?; + // --------------------------------------------------------------------- + // Permissions sources + // --------------------------------------------------------------------- - // Index: idx_group_member_user_id - manager - .create_index( - Index::create() - .name("idx_group_member_user_id") - .table(Alias::new("group_member")) - .col(Alias::new("user_id")) - .to_owned(), - ) - .await?; - - // Create table `user_permission` manager .create_table( Table::create() - .table(Alias::new("user_permission")) + .table(Alias::new("group_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("id")) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(Alias::new("group_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("server_id")).uuid().not_null()) + .col( + ColumnDef::new(Alias::new("scope_type")) + .integer() + .not_null(), + ) + .col(ColumnDef::new(Alias::new("scope_id")).uuid().not_null()) .col( ColumnDef::new(Alias::new("server_permissions")) .big_integer() @@ -650,7 +475,68 @@ impl MigrationTrait for Migration { .default(0), ) .col( - ColumnDef::new("created_at") + ColumnDef::new(Alias::new("created_at")) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .foreign_key( + ForeignKey::create() + .name("fk_group_permission_group") + .from(Alias::new("group_permission"), Alias::new("group_id")) + .to(Alias::new("group"), Alias::new("id")) + .on_delete(ForeignKeyAction::Cascade), + ) + .foreign_key( + ForeignKey::create() + .name("fk_group_permission_server") + .from(Alias::new("group_permission"), Alias::new("server_id")) + .to(Alias::new("server"), Alias::new("id")) + .on_delete(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await?; + + manager + .create_table( + Table::create() + .table(Alias::new("user_permission")) + .if_not_exists() + .col( + ColumnDef::new(Alias::new("id")) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(Alias::new("user_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("server_id")).uuid().not_null()) + .col( + ColumnDef::new(Alias::new("scope_type")) + .integer() + .not_null(), + ) + .col(ColumnDef::new(Alias::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(Alias::new("created_at")) .timestamp_with_time_zone() .not_null() .default(Expr::current_timestamp()), @@ -673,14 +559,22 @@ impl MigrationTrait for Migration { ) .await?; - // Create CACHE table `computed_permission` + // --------------------------------------------------------------------- + // Cache des permissions calculées + // --------------------------------------------------------------------- + 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("user_id")).uuid().not_null()) + .col( + ColumnDef::new(Alias::new("scope_type")) + .integer() + .not_null(), + ) + .col(ColumnDef::new(Alias::new("resource_id")).uuid().not_null()) .col( ColumnDef::new(Alias::new("server_permissions")) .big_integer() @@ -702,6 +596,7 @@ impl MigrationTrait for Migration { .primary_key( Index::create() .col(Alias::new("user_id")) + .col(Alias::new("scope_type")) .col(Alias::new("resource_id")), ) .foreign_key( @@ -715,41 +610,117 @@ impl MigrationTrait for Migration { ) .await?; + // --------------------------------------------------------------------- + // Index + // --------------------------------------------------------------------- + + let indexes = [ + ("idx_category_server_id", "category", "server_id"), + ("idx_channel_server_id", "channel", "server_id"), + ("idx_channel_category_id", "channel", "category_id"), + ("idx_message_channel_id", "message", "channel_id"), + ("idx_message_user_id", "message", "user_id"), + ("idx_attachment_message_id", "attachment", "message_id"), + ("idx_server_user_server_id", "server_user", "server_id"), + ("idx_server_user_user_id", "server_user", "user_id"), + ("idx_channel_user_channel_id", "channel_user", "channel_id"), + ("idx_channel_user_user_id", "channel_user", "user_id"), + ("idx_group_server_id", "group", "server_id"), + ("idx_group_member_user_id", "group_member", "user_id"), + ]; + + for (name, table, column) in indexes { + manager + .create_index( + Index::create() + .name(name) + .table(Alias::new(table)) + .col(Alias::new(column)) + .to_owned(), + ) + .await?; + } + + manager + .create_index( + Index::create() + .name("idx_group_permission_group_scope") + .table(Alias::new("group_permission")) + .col(Alias::new("group_id")) + .col(Alias::new("scope_type")) + .col(Alias::new("scope_id")) + .to_owned(), + ) + .await?; + + manager + .create_index( + Index::create() + .name("idx_group_permission_server") + .table(Alias::new("group_permission")) + .col(Alias::new("server_id")) + .to_owned(), + ) + .await?; + + manager + .create_index( + Index::create() + .name("idx_user_permission_user_scope") + .table(Alias::new("user_permission")) + .col(Alias::new("user_id")) + .col(Alias::new("scope_type")) + .col(Alias::new("scope_id")) + .to_owned(), + ) + .await?; + + manager + .create_index( + Index::create() + .name("idx_user_permission_server") + .table(Alias::new("user_permission")) + .col(Alias::new("server_id")) + .to_owned(), + ) + .await?; + + manager + .create_index( + Index::create() + .name("idx_computed_permission_resource") + .table(Alias::new("computed_permission")) + .col(Alias::new("scope_type")) + .col(Alias::new("resource_id")) + .to_owned(), + ) + .await?; + Ok(()) } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(Alias::new("group_member")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("group")).to_owned()) - .await?; + let tables = [ + "computed_permission", + "user_permission", + "group_permission", + "group_member", + "channel_user", + "server_user", + "attachment", + "message", + "channel", + "category", + "group", + "server", + "user", + ]; - manager - .drop_table(Table::drop().table(Alias::new("channel_user")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("server_user")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("attachment")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("message")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("channel")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("category")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("user")).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Alias::new("server")).to_owned()) - .await?; + for table in tables { + manager + .drop_table(Table::drop().table(Alias::new(table)).to_owned()) + .await?; + } Ok(()) } diff --git a/src/models/computed_permission.rs b/src/models/computed_permission.rs index 019f8c6..1e6a34f 100644 --- a/src/models/computed_permission.rs +++ b/src/models/computed_permission.rs @@ -1,4 +1,22 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.19 +/// Permet de cache les permissions des utilisateurs pour éviter de recalculer les permissions à chaque fois qu'une requête est faite. 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 = "computed_permission")] @@ -7,7 +25,9 @@ pub struct Model { #[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) + pub scope_type: PermissionScopeType, + + /// L'ID de la ressource (soit un Uuid d'une Category, soit l'Uuid d'un Channel, soit l'Uuid du Server) #[sea_orm(primary_key, auto_increment = false)] pub resource_id: Uuid, diff --git a/src/models/group_member.rs b/src/models/group_member.rs index 8e956b8..847c178 100644 --- a/src/models/group_member.rs +++ b/src/models/group_member.rs @@ -1,21 +1,6 @@ //! `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")] @@ -24,8 +9,6 @@ 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/group_permission.rs b/src/models/group_permission.rs new file mode 100644 index 0000000..25ce074 --- /dev/null +++ b/src/models/group_permission.rs @@ -0,0 +1,66 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.19 +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_permission")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Uuid, + pub group_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::group::Entity", + from = "Column::GroupId", + to = "super::group::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Group, + #[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::Group.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Server.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/models/mod.rs b/src/models/mod.rs index 1750f15..fbe3d63 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -6,11 +6,12 @@ pub mod attachment; pub mod category; pub mod channel; pub mod channel_user; -mod computed_permission; +pub mod computed_permission; pub mod group; pub mod group_member; +pub mod group_permission; pub mod message; pub mod server; pub mod server_user; pub mod user; -mod user_permission; +pub mod user_permission; diff --git a/src/models/prelude.rs b/src/models/prelude.rs index 12070eb..c61eeb1 100644 --- a/src/models/prelude.rs +++ b/src/models/prelude.rs @@ -4,9 +4,12 @@ pub use super::attachment::Entity as Attachment; pub use super::category::Entity as Category; pub use super::channel::Entity as Channel; pub use super::channel_user::Entity as ChannelUser; +pub use super::computed_permission::Entity as ComputedPermission; pub use super::group::Entity as Group; pub use super::group_member::Entity as GroupMember; +pub use super::group_permission::Entity as GroupPermission; pub use super::message::Entity as Message; pub use super::server::Entity as Server; pub use super::server_user::Entity as ServerUser; pub use super::user::Entity as User; +pub use super::user_permission::Entity as UserPermission; diff --git a/src/models/server.rs b/src/models/server.rs index 61f8e86..a993205 100644 --- a/src/models/server.rs +++ b/src/models/server.rs @@ -14,7 +14,7 @@ pub struct Model { pub created_at: DateTimeUtc, pub updated_at: DateTimeUtc, pub is_default: bool, - pub owned_id: Uuid, + pub owner_id: Uuid, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/models/user_permission.rs b/src/models/user_permission.rs index 61fdb61..7e9736e 100644 --- a/src/models/user_permission.rs +++ b/src/models/user_permission.rs @@ -1,5 +1,20 @@ -use super::group_member::PermissionScopeType; +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.19 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 = "user_permission")] diff --git a/src/repositories/computed_permission.rs b/src/repositories/computed_permission.rs new file mode 100644 index 0000000..2010e9e --- /dev/null +++ b/src/repositories/computed_permission.rs @@ -0,0 +1,51 @@ +use crate::models::{computed_permission, group, group_member, server, user}; +use crate::repositories::{AnyResult, RepositoryContext}; +// use sea_orm::prelude::*; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; + +use std::sync::Arc; +use uuid::Uuid; + +#[derive(Clone, Debug)] +pub struct ComputedPermissionRepository { + pub context: Arc, +} + +impl ComputedPermissionRepository { + pub async fn get_all(&self) -> AnyResult> { + let result = computed_permission::Entity::find() + .all(&self.context.db) + .await?; + Ok(result) + } + + pub async fn full_sync_server(&self, server_id: Uuid) -> AnyResult<()> { + Ok(()) + } + + pub async fn full_sync_user(&self, user_id: Uuid, server_id: Uuid) -> AnyResult<()> { + // 1. Récupérer la structure (tous les salons + catégories du serveur) + // 2. Récupérer les sources de vérité (Groupes de l'user + Perms individuelles) + // 3. Calculer pour l'UUID du serveur (Pseudo-salon pour le Kick/Ban) + // 4. Pour chaque salon, calculer la fusion des bits + // 5. Tout enregistrer en une seule transaction dans `computed_permission` + + // Récupération du serveur + let server = server::Entity::find_by_id(server_id) + .one(&self.context.db) + .await?; + + // Récupération de l'utilisateur + let user = user::Entity::find_by_id(user_id) + .one(&self.context.db) + .await?; + + // Récupération des groupes de l'utilisateur + let groups = group::Entity::find() + .filter(group::Column::ServerId.eq(server_id)) + .filter(group_member::Column::UserId.eq(user_id)) + .all(&self.context.db) + .await?; + Ok(()) + } +} diff --git a/src/repositories/mod.rs b/src/repositories/mod.rs index 749b2cc..a07b251 100644 --- a/src/repositories/mod.rs +++ b/src/repositories/mod.rs @@ -2,6 +2,7 @@ pub type AnyResult = anyhow::Result; use crate::repositories::category::CategoryRepository; use crate::repositories::channel::ChannelRepository; +use crate::repositories::computed_permission::ComputedPermissionRepository; use crate::repositories::group::GroupRepository; use crate::repositories::message::MessageRepository; use crate::repositories::server::ServerRepository; @@ -12,6 +13,7 @@ use std::sync::Arc; mod category; mod channel; +mod computed_permission; mod group; mod message; mod server; @@ -32,6 +34,7 @@ pub struct Repositories { pub group: GroupRepository, pub message: MessageRepository, pub user: UserRepository, + pub computed_permission: ComputedPermissionRepository, } impl Repositories { @@ -57,6 +60,9 @@ impl Repositories { user: UserRepository { context: context.clone(), }, + computed_permission: ComputedPermissionRepository { + context: context.clone(), + }, } } } diff --git a/src/repositories/server.rs b/src/repositories/server.rs index a9c2d4c..7f8a30c 100644 --- a/src/repositories/server.rs +++ b/src/repositories/server.rs @@ -40,7 +40,7 @@ impl ServerRepository { // Créer le groupe par défaut pour le serveur let default_group = group::ActiveModel { server_id: Set(server.id), - name: Set("Membres".to_string()), + name: Set("Member".to_string()), is_default: Set(true), ..Default::default() };