feat(db): add auth schema migrations (10 tables)
- users with partial unique index on (tenant_id, username) WHERE deleted_at IS NULL - user_credentials, user_tokens with FK cascade - roles, permissions with composite unique (tenant_id, code) - role_permissions, user_roles junction tables - organizations (self-ref tree), departments (tree + org FK), positions - All tables include standard fields: id, tenant_id, timestamps, soft delete, version
This commit is contained in:
@@ -1,12 +1,34 @@
|
|||||||
pub use sea_orm_migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20260410_000001_create_tenant;
|
mod m20260410_000001_create_tenant;
|
||||||
|
mod m20260411_000002_create_users;
|
||||||
|
mod m20260411_000003_create_user_credentials;
|
||||||
|
mod m20260411_000004_create_user_tokens;
|
||||||
|
mod m20260411_000005_create_roles;
|
||||||
|
mod m20260411_000006_create_permissions;
|
||||||
|
mod m20260411_000007_create_role_permissions;
|
||||||
|
mod m20260411_000008_create_user_roles;
|
||||||
|
mod m20260411_000009_create_organizations;
|
||||||
|
mod m20260411_000010_create_departments;
|
||||||
|
mod m20260411_000011_create_positions;
|
||||||
|
|
||||||
pub struct Migrator;
|
pub struct Migrator;
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl MigratorTrait for Migrator {
|
impl MigratorTrait for Migrator {
|
||||||
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
||||||
vec![Box::new(m20260410_000001_create_tenant::Migration)]
|
vec![
|
||||||
|
Box::new(m20260410_000001_create_tenant::Migration),
|
||||||
|
Box::new(m20260411_000002_create_users::Migration),
|
||||||
|
Box::new(m20260411_000003_create_user_credentials::Migration),
|
||||||
|
Box::new(m20260411_000004_create_user_tokens::Migration),
|
||||||
|
Box::new(m20260411_000005_create_roles::Migration),
|
||||||
|
Box::new(m20260411_000006_create_permissions::Migration),
|
||||||
|
Box::new(m20260411_000007_create_role_permissions::Migration),
|
||||||
|
Box::new(m20260411_000008_create_user_roles::Migration),
|
||||||
|
Box::new(m20260411_000009_create_organizations::Migration),
|
||||||
|
Box::new(m20260411_000010_create_departments::Migration),
|
||||||
|
Box::new(m20260411_000011_create_positions::Migration),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
109
crates/erp-server/migration/src/m20260411_000002_create_users.rs
Normal file
109
crates/erp-server/migration/src/m20260411_000002_create_users.rs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Users::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Users::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Users::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Users::Username).string().not_null())
|
||||||
|
.col(ColumnDef::new(Users::Email).string().null())
|
||||||
|
.col(ColumnDef::new(Users::Phone).string().null())
|
||||||
|
.col(ColumnDef::new(Users::DisplayName).string().null())
|
||||||
|
.col(ColumnDef::new(Users::AvatarUrl).string().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Users::Status)
|
||||||
|
.string()
|
||||||
|
.not_null()
|
||||||
|
.default("active"),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Users::LastLoginAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Users::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Users::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Users::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Users::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Users::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Users::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_users_tenant_id")
|
||||||
|
.table(Users::Table)
|
||||||
|
.col(Users::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager.get_connection().execute(sea_orm::Statement::from_string(
|
||||||
|
sea_orm::DatabaseBackend::Postgres,
|
||||||
|
"CREATE UNIQUE INDEX idx_users_tenant_username ON users (tenant_id, username) WHERE deleted_at IS NULL".to_string(),
|
||||||
|
)).await.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Users::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Users {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
Username,
|
||||||
|
Email,
|
||||||
|
Phone,
|
||||||
|
DisplayName,
|
||||||
|
AvatarUrl,
|
||||||
|
Status,
|
||||||
|
LastLoginAt,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(UserCredentials::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserCredentials::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserCredentials::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(UserCredentials::UserId).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserCredentials::CredentialType)
|
||||||
|
.string()
|
||||||
|
.not_null()
|
||||||
|
.default("password"),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserCredentials::CredentialData).json().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserCredentials::Verified)
|
||||||
|
.boolean()
|
||||||
|
.not_null()
|
||||||
|
.default(false),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserCredentials::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserCredentials::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserCredentials::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(UserCredentials::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserCredentials::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserCredentials::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_user_credentials_user_id")
|
||||||
|
.from(UserCredentials::Table, UserCredentials::UserId)
|
||||||
|
.to(Users::Table, Users::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_user_credentials_tenant_id")
|
||||||
|
.table(UserCredentials::Table)
|
||||||
|
.col(UserCredentials::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_user_credentials_user_id")
|
||||||
|
.table(UserCredentials::Table)
|
||||||
|
.col(UserCredentials::UserId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(UserCredentials::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum UserCredentials {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
UserId,
|
||||||
|
CredentialType,
|
||||||
|
CredentialData,
|
||||||
|
Verified,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Users {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(UserTokens::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserTokens::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(UserTokens::UserId).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::TokenHash)
|
||||||
|
.string()
|
||||||
|
.not_null()
|
||||||
|
.unique_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserTokens::TokenType).string().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::ExpiresAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::RevokedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserTokens::DeviceInfo).string().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserTokens::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(UserTokens::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserTokens::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_user_tokens_user_id")
|
||||||
|
.from(UserTokens::Table, UserTokens::UserId)
|
||||||
|
.to(Users::Table, Users::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_user_tokens_tenant_id")
|
||||||
|
.table(UserTokens::Table)
|
||||||
|
.col(UserTokens::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_user_tokens_user_id")
|
||||||
|
.table(UserTokens::Table)
|
||||||
|
.col(UserTokens::UserId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_user_tokens_token_hash")
|
||||||
|
.table(UserTokens::Table)
|
||||||
|
.col(UserTokens::TokenHash)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(UserTokens::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum UserTokens {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
UserId,
|
||||||
|
TokenHash,
|
||||||
|
TokenType,
|
||||||
|
ExpiresAt,
|
||||||
|
RevokedAt,
|
||||||
|
DeviceInfo,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Users {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
106
crates/erp-server/migration/src/m20260411_000005_create_roles.rs
Normal file
106
crates/erp-server/migration/src/m20260411_000005_create_roles.rs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Roles::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Roles::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Roles::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Roles::Name).string().not_null())
|
||||||
|
.col(ColumnDef::new(Roles::Code).string().not_null())
|
||||||
|
.col(ColumnDef::new(Roles::Description).text().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Roles::IsSystem)
|
||||||
|
.boolean()
|
||||||
|
.not_null()
|
||||||
|
.default(false),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Roles::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Roles::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Roles::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Roles::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Roles::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Roles::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_roles_tenant_id")
|
||||||
|
.table(Roles::Table)
|
||||||
|
.col(Roles::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_roles_tenant_code")
|
||||||
|
.table(Roles::Table)
|
||||||
|
.col(Roles::TenantId)
|
||||||
|
.col(Roles::Code)
|
||||||
|
.unique()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Roles::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Roles {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
Name,
|
||||||
|
Code,
|
||||||
|
Description,
|
||||||
|
IsSystem,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Permissions::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Permissions::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Permissions::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Permissions::Code).string().not_null())
|
||||||
|
.col(ColumnDef::new(Permissions::Name).string().not_null())
|
||||||
|
.col(ColumnDef::new(Permissions::Resource).string().not_null())
|
||||||
|
.col(ColumnDef::new(Permissions::Action).string().not_null())
|
||||||
|
.col(ColumnDef::new(Permissions::Description).text().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Permissions::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Permissions::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Permissions::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Permissions::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Permissions::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Permissions::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_permissions_tenant_id")
|
||||||
|
.table(Permissions::Table)
|
||||||
|
.col(Permissions::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_permissions_tenant_code")
|
||||||
|
.table(Permissions::Table)
|
||||||
|
.col(Permissions::TenantId)
|
||||||
|
.col(Permissions::Code)
|
||||||
|
.unique()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Permissions::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Permissions {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
Code,
|
||||||
|
Name,
|
||||||
|
Resource,
|
||||||
|
Action,
|
||||||
|
Description,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(RolePermissions::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(RolePermissions::RoleId)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(RolePermissions::PermissionId)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(RolePermissions::TenantId).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(RolePermissions::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(RolePermissions::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(RolePermissions::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(RolePermissions::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(RolePermissions::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(RolePermissions::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_role_permissions_role_id")
|
||||||
|
.from(RolePermissions::Table, RolePermissions::RoleId)
|
||||||
|
.to(Roles::Table, Roles::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_role_permissions_permission_id")
|
||||||
|
.from(RolePermissions::Table, RolePermissions::PermissionId)
|
||||||
|
.to(Permissions::Table, Permissions::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_role_permissions_tenant_id")
|
||||||
|
.table(RolePermissions::Table)
|
||||||
|
.col(RolePermissions::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(RolePermissions::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum RolePermissions {
|
||||||
|
Table,
|
||||||
|
RoleId,
|
||||||
|
PermissionId,
|
||||||
|
TenantId,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Roles {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Permissions {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(UserRoles::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserRoles::UserId)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserRoles::RoleId)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserRoles::TenantId).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserRoles::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserRoles::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(UserRoles::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(UserRoles::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserRoles::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(UserRoles::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_user_roles_user_id")
|
||||||
|
.from(UserRoles::Table, UserRoles::UserId)
|
||||||
|
.to(Users::Table, Users::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_user_roles_role_id")
|
||||||
|
.from(UserRoles::Table, UserRoles::RoleId)
|
||||||
|
.to(Roles::Table, Roles::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_user_roles_tenant_id")
|
||||||
|
.table(UserRoles::Table)
|
||||||
|
.col(UserRoles::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(UserRoles::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum UserRoles {
|
||||||
|
Table,
|
||||||
|
UserId,
|
||||||
|
RoleId,
|
||||||
|
TenantId,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Users {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Roles {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Organizations::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Organizations::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Organizations::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Organizations::Name).string().not_null())
|
||||||
|
.col(ColumnDef::new(Organizations::Code).string().null())
|
||||||
|
.col(ColumnDef::new(Organizations::ParentId).uuid().null())
|
||||||
|
.col(ColumnDef::new(Organizations::Path).string().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Organizations::Level)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(0),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Organizations::SortOrder)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(0),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Organizations::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Organizations::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Organizations::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Organizations::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Organizations::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Organizations::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_organizations_parent_id")
|
||||||
|
.from(Organizations::Table, Organizations::ParentId)
|
||||||
|
.to(Organizations::Table, Organizations::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Restrict)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_organizations_tenant_id")
|
||||||
|
.table(Organizations::Table)
|
||||||
|
.col(Organizations::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager.get_connection().execute(sea_orm::Statement::from_string(
|
||||||
|
sea_orm::DatabaseBackend::Postgres,
|
||||||
|
"CREATE UNIQUE INDEX idx_organizations_tenant_code ON organizations (tenant_id, code) WHERE code IS NOT NULL".to_string(),
|
||||||
|
)).await.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Organizations::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Organizations {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
Name,
|
||||||
|
Code,
|
||||||
|
ParentId,
|
||||||
|
Path,
|
||||||
|
Level,
|
||||||
|
SortOrder,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Departments::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Departments::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Departments::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Departments::OrgId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Departments::Name).string().not_null())
|
||||||
|
.col(ColumnDef::new(Departments::Code).string().null())
|
||||||
|
.col(ColumnDef::new(Departments::ParentId).uuid().null())
|
||||||
|
.col(ColumnDef::new(Departments::ManagerId).uuid().null())
|
||||||
|
.col(ColumnDef::new(Departments::Path).string().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Departments::SortOrder)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(0),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Departments::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Departments::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Departments::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Departments::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Departments::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Departments::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_departments_org_id")
|
||||||
|
.from(Departments::Table, Departments::OrgId)
|
||||||
|
.to(Organizations::Table, Organizations::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Restrict)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_departments_parent_id")
|
||||||
|
.from(Departments::Table, Departments::ParentId)
|
||||||
|
.to(Departments::Table, Departments::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Restrict)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_departments_manager_id")
|
||||||
|
.from(Departments::Table, Departments::ManagerId)
|
||||||
|
.to(Users::Table, Users::Id)
|
||||||
|
.on_delete(ForeignKeyAction::SetNull)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_departments_tenant_id")
|
||||||
|
.table(Departments::Table)
|
||||||
|
.col(Departments::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_departments_org_id")
|
||||||
|
.table(Departments::Table)
|
||||||
|
.col(Departments::OrgId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Departments::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Departments {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
OrgId,
|
||||||
|
Name,
|
||||||
|
Code,
|
||||||
|
ParentId,
|
||||||
|
ManagerId,
|
||||||
|
Path,
|
||||||
|
SortOrder,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Organizations {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Users {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
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> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Positions::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Positions::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Positions::TenantId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Positions::DeptId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Positions::Name).string().not_null())
|
||||||
|
.col(ColumnDef::new(Positions::Code).string().null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Positions::Level)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(0),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Positions::SortOrder)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(0),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Positions::CreatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Positions::UpdatedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.not_null()
|
||||||
|
.default(Expr::current_timestamp()),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Positions::CreatedBy).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Positions::UpdatedBy).uuid().not_null())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Positions::DeletedAt)
|
||||||
|
.timestamp_with_time_zone()
|
||||||
|
.null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Positions::Version)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.default(1),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
&mut ForeignKey::create()
|
||||||
|
.name("fk_positions_dept_id")
|
||||||
|
.from(Positions::Table, Positions::DeptId)
|
||||||
|
.to(Departments::Table, Departments::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Restrict)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_positions_tenant_id")
|
||||||
|
.table(Positions::Table)
|
||||||
|
.col(Positions::TenantId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("idx_positions_dept_id")
|
||||||
|
.table(Positions::Table)
|
||||||
|
.col(Positions::DeptId)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Positions::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Positions {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
TenantId,
|
||||||
|
DeptId,
|
||||||
|
Name,
|
||||||
|
Code,
|
||||||
|
Level,
|
||||||
|
SortOrder,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CreatedBy,
|
||||||
|
UpdatedBy,
|
||||||
|
DeletedAt,
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
enum Departments {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user