use sea_orm_migration::prelude::*; #[derive(DeriveMigrationName)] pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { // --------------------------------------------------------------------- // Utilisateurs // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("user")) .if_not_exists() .col( ColumnDef::new(Alias::new("id")) .uuid() .not_null() .primary_key(), ) .col(ColumnDef::new(Alias::new("username")).string().not_null()) .col(ColumnDef::new(Alias::new("password")).string().not_null()) .col( ColumnDef::new(Alias::new("pub_key")) .text() .null() .unique_key(), ) .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_superuser")) .boolean() .not_null() .default(false), ) .to_owned(), ) .await?; // --------------------------------------------------------------------- // Serveurs // --------------------------------------------------------------------- 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().null()) .foreign_key( ForeignKey::create() .name("fk_server_owner") .from(Alias::new("server"), Alias::new("owner_id")) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::SetNull), ) .to_owned(), ) .await?; manager .create_table( Table::create() .table(Alias::new("server_user")) .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("user_id")).uuid().not_null()) .col(ColumnDef::new(Alias::new("username")).string().null()) .col( ColumnDef::new(Alias::new("joined_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_server_user_server") .from(Alias::new("server_user"), Alias::new("server_id")) .to(Alias::new("server"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_server_user_user") .from(Alias::new("server_user"), Alias::new("user_id")) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_server_user") .table(Alias::new("server_user")) .col(Alias::new("server_id")) .col(Alias::new("user_id")) .unique() .to_owned(), ) .await?; // --------------------------------------------------------------------- // Rôles // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("role")) .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("is_default")) .boolean() .not_null() .default(false), ) .col( ColumnDef::new(Alias::new("created_at")) .timestamp_with_time_zone() .not_null() .default(Expr::current_timestamp()), ) .foreign_key( ForeignKey::create() .name("fk_role_server") .from(Alias::new("role"), Alias::new("server_id")) .to(Alias::new("server"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_role_server_name") .table(Alias::new("role")) .col(Alias::new("server_id")) .col(Alias::new("name")) .unique() .to_owned(), ) .await?; manager .create_table( Table::create() .table(Alias::new("role_user")) .if_not_exists() .col(ColumnDef::new(Alias::new("role_id")).uuid().not_null()) .col(ColumnDef::new(Alias::new("user_id")).uuid().not_null()) .primary_key( Index::create() .col(Alias::new("role_id")) .col(Alias::new("user_id")), ) .foreign_key( ForeignKey::create() .name("fk_role_user_role") .from(Alias::new("role_user"), Alias::new("role_id")) .to(Alias::new("role"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_role_user_user") .from(Alias::new("role_user"), Alias::new("user_id")) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; // --------------------------------------------------------------------- // Catégories et canaux // --------------------------------------------------------------------- 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("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), ) .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("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?; // --------------------------------------------------------------------- // Ordre des catégories et des canaux (Polymorphique) // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("server_item_order")) .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("resource_id")).uuid().not_null()) .col( ColumnDef::new(Alias::new("resource_type")) .integer() .not_null(), ) .col( ColumnDef::new(Alias::new("parent_category_id")) .uuid() .null(), ) .col( ColumnDef::new(Alias::new("order_key")) .big_integer() .not_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_server_item_order_server") .from(Alias::new("server_item_order"), Alias::new("server_id")) .to(Alias::new("server"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_server_item_order_parent_category") .from( Alias::new("server_item_order"), Alias::new("parent_category_id"), ) .to(Alias::new("category"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("idx_server_item_order_scope") .table(Alias::new("server_item_order")) .col(Alias::new("server_id")) .col(Alias::new("parent_category_id")) .col(Alias::new("order_key")) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_server_item_order_resource") .table(Alias::new("server_item_order")) .col(Alias::new("server_id")) .col(Alias::new("resource_type")) .col(Alias::new("resource_id")) .unique() .to_owned(), ) .await?; // --------------------------------------------------------------------- // Membres des canaux // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("channel_user")) .if_not_exists() .col( ColumnDef::new(Alias::new("id")) .uuid() .not_null() .primary_key(), ) .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()), ) .foreign_key( ForeignKey::create() .name("fk_channel_user_channel") .from(Alias::new("channel_user"), Alias::new("channel_id")) .to(Alias::new("channel"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_channel_user_user") .from(Alias::new("channel_user"), Alias::new("user_id")) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_channel_user") .table(Alias::new("channel_user")) .col(Alias::new("channel_id")) .col(Alias::new("user_id")) .unique() .to_owned(), ) .await?; // --------------------------------------------------------------------- // Position de lecture des utilisateurs // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("channel_user_read_state")) .if_not_exists() .col( ColumnDef::new(Alias::new("id")) .uuid() .not_null() .primary_key(), ) .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("last_read_message_id")) .uuid() .null(), ) .col( ColumnDef::new(Alias::new("updated_at")) .timestamp_with_time_zone() .not_null() .default(Expr::current_timestamp()), ) .foreign_key( ForeignKey::create() .name("fk_channel_user_read_state_channel") .from( Alias::new("channel_user_read_state"), Alias::new("channel_id"), ) .to(Alias::new("channel"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_channel_user_read_state_user") .from( Alias::new("channel_user_read_state"), Alias::new("user_id"), ) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_channel_user_read_state") .table(Alias::new("channel_user_read_state")) .col(Alias::new("channel_id")) .col(Alias::new("user_id")) .unique() .to_owned(), ) .await?; // --------------------------------------------------------------------- // Messages et pièces jointes // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("message")) .if_not_exists() .col( ColumnDef::new(Alias::new("id")) .uuid() .not_null() .primary_key(), ) .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("content")).text().not_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() .null(), ) .col(ColumnDef::new(Alias::new("reply_to_id")).uuid().null()) .foreign_key( ForeignKey::create() .name("fk_message_channel") .from(Alias::new("message"), Alias::new("channel_id")) .to(Alias::new("channel"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_message_user") .from(Alias::new("message"), Alias::new("user_id")) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_message_reply_to") .from(Alias::new("message"), Alias::new("reply_to_id")) .to(Alias::new("message"), Alias::new("id")) .on_delete(ForeignKeyAction::SetNull), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("idx_message_channel_id_id") .table(Alias::new("message")) .col(Alias::new("channel_id")) .col(Alias::new("id")) .to_owned(), ) .await?; manager .create_table( Table::create() .table(Alias::new("attachment")) .if_not_exists() .col( ColumnDef::new(Alias::new("id")) .uuid() .not_null() .primary_key(), ) .col(ColumnDef::new(Alias::new("message_id")).uuid().not_null()) .col(ColumnDef::new(Alias::new("filename")).string().not_null()) .col( ColumnDef::new(Alias::new("file_size")) .big_integer() .not_null(), ) .col(ColumnDef::new(Alias::new("mime_type")).string().not_null()) .col( ColumnDef::new(Alias::new("created_at")) .timestamp_with_time_zone() .not_null() .default(Expr::current_timestamp()), ) .foreign_key( ForeignKey::create() .name("fk_attachment_message") .from(Alias::new("attachment"), Alias::new("message_id")) .to(Alias::new("message"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; // --------------------------------------------------------------------- // Permissions // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("server_user_permission")) .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("user_id")).uuid().not_null()) .col( ColumnDef::new(Alias::new("permissions")) .big_integer() .not_null() .default(0), ) .foreign_key( ForeignKey::create() .name("fk_server_user_permission_server") .from( Alias::new("server_user_permission"), Alias::new("server_id"), ) .to(Alias::new("server"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_server_user_permission_user") .from(Alias::new("server_user_permission"), Alias::new("user_id")) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_server_user_permission") .table(Alias::new("server_user_permission")) .col(Alias::new("server_id")) .col(Alias::new("user_id")) .unique() .to_owned(), ) .await?; manager .create_table( Table::create() .table(Alias::new("server_role_permission")) .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("role_id")).uuid().not_null()) .col( ColumnDef::new(Alias::new("permissions")) .big_integer() .not_null() .default(0), ) .foreign_key( ForeignKey::create() .name("fk_server_role_permission_server") .from( Alias::new("server_role_permission"), Alias::new("server_id"), ) .to(Alias::new("server"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_server_role_permission_role") .from(Alias::new("server_role_permission"), Alias::new("role_id")) .to(Alias::new("role"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_server_role_permission") .table(Alias::new("server_role_permission")) .col(Alias::new("server_id")) .col(Alias::new("role_id")) .unique() .to_owned(), ) .await?; manager .create_table( Table::create() .table(Alias::new("channel_role_permission")) .if_not_exists() .col( ColumnDef::new(Alias::new("id")) .uuid() .not_null() .primary_key(), ) .col(ColumnDef::new(Alias::new("channel_id")).uuid().not_null()) .col(ColumnDef::new(Alias::new("role_id")).uuid().not_null()) .col( ColumnDef::new(Alias::new("permissions")) .big_integer() .not_null() .default(0), ) .foreign_key( ForeignKey::create() .name("fk_channel_role_permission_channel") .from( Alias::new("channel_role_permission"), Alias::new("channel_id"), ) .to(Alias::new("channel"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_channel_role_permission_role") .from(Alias::new("channel_role_permission"), Alias::new("role_id")) .to(Alias::new("role"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_channel_role_permission") .table(Alias::new("channel_role_permission")) .col(Alias::new("channel_id")) .col(Alias::new("role_id")) .unique() .to_owned(), ) .await?; manager .create_table( Table::create() .table(Alias::new("channel_user_permission")) .if_not_exists() .col( ColumnDef::new(Alias::new("id")) .uuid() .not_null() .primary_key(), ) .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("permissions")) .big_integer() .not_null() .default(0), ) .foreign_key( ForeignKey::create() .name("fk_channel_user_permission_channel") .from( Alias::new("channel_user_permission"), Alias::new("channel_id"), ) .to(Alias::new("channel"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk_channel_user_permission_user") .from(Alias::new("channel_user_permission"), Alias::new("user_id")) .to(Alias::new("user"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; manager .create_index( Index::create() .name("uq_channel_user_permission") .table(Alias::new("channel_user_permission")) .col(Alias::new("channel_id")) .col(Alias::new("user_id")) .unique() .to_owned(), ) .await?; // --------------------------------------------------------------------- // Cache des permissions calculées // --------------------------------------------------------------------- manager .create_table( Table::create() .table(Alias::new("computed_permission")) .if_not_exists() .col(ColumnDef::new(Alias::new("id")).uuid().not_null()) .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("resource_id")).uuid().not_null()) .col( ColumnDef::new(Alias::new("permissions")) .big_integer() .not_null() .default(0), ) .primary_key( Index::create() .col(Alias::new("id")) .col(Alias::new("user_id")) .col(Alias::new("server_id")) .col(Alias::new("scope_type")) .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), ) .foreign_key( ForeignKey::create() .name("fk_computed_permission_server") .from(Alias::new("computed_permission"), Alias::new("server_id")) .to(Alias::new("server"), Alias::new("id")) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; Ok(()) } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { let tables = [ "computed_permission", "channel_user_read_state", "channel_user_permission", "channel_role_permission", "server_user_permission", "server_role_permission", "attachment", "message", "channel_user", "server_item_order", "channel", "category", "role_user", "role", "server_user", "server", "user", ]; for table in tables { manager .drop_table( Table::drop() .table(Alias::new(table)) .if_exists() .to_owned(), ) .await?; } Ok(()) } }