chore: apply cargo fmt across workspace and update docs
- Run cargo fmt on all Rust crates for consistent formatting - Update CLAUDE.md with WASM plugin commands and dev.ps1 instructions - Update wiki: add WASM plugin architecture, rewrite dev environment docs - Minor frontend cleanup (unused imports)
This commit is contained in:
@@ -29,6 +29,7 @@ mod m20260413_000026_create_audit_logs;
|
||||
mod m20260414_000027_fix_unique_indexes_soft_delete;
|
||||
mod m20260414_000028_add_standard_fields_to_tokens;
|
||||
mod m20260414_000029_add_standard_fields_to_process_variables;
|
||||
mod m20260414_000032_fix_settings_unique_index_null;
|
||||
mod m20260415_000030_add_version_to_message_tables;
|
||||
mod m20260416_000031_create_domain_events;
|
||||
|
||||
@@ -69,6 +70,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260414_000029_add_standard_fields_to_process_variables::Migration),
|
||||
Box::new(m20260415_000030_add_version_to_message_tables::Migration),
|
||||
Box::new(m20260416_000031_create_domain_events::Migration),
|
||||
Box::new(m20260414_000032_fix_settings_unique_index_null::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Tenant::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Tenant::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(Tenant::Id).uuid().not_null().primary_key())
|
||||
.col(ColumnDef::new(Tenant::Name).string().not_null())
|
||||
.col(
|
||||
ColumnDef::new(Tenant::Code)
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Users::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Users::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.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())
|
||||
|
||||
@@ -25,7 +25,11 @@ impl MigrationTrait for Migration {
|
||||
.not_null()
|
||||
.default("password"),
|
||||
)
|
||||
.col(ColumnDef::new(UserCredentials::CredentialData).json().null())
|
||||
.col(
|
||||
ColumnDef::new(UserCredentials::CredentialData)
|
||||
.json()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(UserCredentials::Verified)
|
||||
.boolean()
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Roles::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Roles::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.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())
|
||||
|
||||
@@ -12,7 +12,11 @@ impl MigrationTrait for Migration {
|
||||
.table(RolePermissions::Table)
|
||||
.if_not_exists()
|
||||
.col(ColumnDef::new(RolePermissions::RoleId).uuid().not_null())
|
||||
.col(ColumnDef::new(RolePermissions::PermissionId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(RolePermissions::PermissionId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(RolePermissions::TenantId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(RolePermissions::CreatedAt)
|
||||
|
||||
@@ -18,7 +18,11 @@ impl MigrationTrait for Migration {
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(DictionaryItems::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(DictionaryItems::DictionaryId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(DictionaryItems::DictionaryId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(DictionaryItems::Label).string().not_null())
|
||||
.col(ColumnDef::new(DictionaryItems::Value).string().not_null())
|
||||
.col(
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Menus::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Menus::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(Menus::Id).uuid().not_null().primary_key())
|
||||
.col(ColumnDef::new(Menus::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(Menus::ParentId).uuid().null())
|
||||
.col(ColumnDef::new(Menus::Title).string().not_null())
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Settings::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Settings::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(Settings::Id).uuid().not_null().primary_key())
|
||||
.col(ColumnDef::new(Settings::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(Settings::Scope).string().not_null())
|
||||
.col(ColumnDef::new(Settings::ScopeId).uuid().null())
|
||||
|
||||
@@ -17,7 +17,11 @@ impl MigrationTrait for Migration {
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessDefinitions::TenantId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessDefinitions::TenantId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessDefinitions::Name).string().not_null())
|
||||
.col(ColumnDef::new(ProcessDefinitions::Key).string().not_null())
|
||||
.col(
|
||||
@@ -27,7 +31,11 @@ impl MigrationTrait for Migration {
|
||||
.default(1),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessDefinitions::Category).string().null())
|
||||
.col(ColumnDef::new(ProcessDefinitions::Description).text().null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessDefinitions::Description)
|
||||
.text()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessDefinitions::Nodes)
|
||||
.json_binary()
|
||||
@@ -58,8 +66,16 @@ impl MigrationTrait for Migration {
|
||||
.not_null()
|
||||
.default(Expr::current_timestamp()),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessDefinitions::CreatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(ProcessDefinitions::UpdatedBy).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessDefinitions::CreatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessDefinitions::UpdatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessDefinitions::DeletedAt)
|
||||
.timestamp_with_time_zone()
|
||||
|
||||
@@ -18,15 +18,27 @@ impl MigrationTrait for Migration {
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessInstances::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(ProcessInstances::DefinitionId).uuid().not_null())
|
||||
.col(ColumnDef::new(ProcessInstances::BusinessKey).string().null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::DefinitionId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::BusinessKey)
|
||||
.string()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::Status)
|
||||
.string()
|
||||
.not_null()
|
||||
.default("running"),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessInstances::StartedBy).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::StartedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::StartedAt)
|
||||
.timestamp_with_time_zone()
|
||||
@@ -50,8 +62,16 @@ impl MigrationTrait for Migration {
|
||||
.not_null()
|
||||
.default(Expr::current_timestamp()),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessInstances::CreatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(ProcessInstances::UpdatedBy).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::CreatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::UpdatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessInstances::DeletedAt)
|
||||
.timestamp_with_time_zone()
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Tokens::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Tokens::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(Tokens::Id).uuid().not_null().primary_key())
|
||||
.col(ColumnDef::new(Tokens::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(Tokens::InstanceId).uuid().not_null())
|
||||
.col(ColumnDef::new(Tokens::NodeId).string().not_null())
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Tasks::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Tasks::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(Tasks::Id).uuid().not_null().primary_key())
|
||||
.col(ColumnDef::new(Tasks::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(Tasks::InstanceId).uuid().not_null())
|
||||
.col(ColumnDef::new(Tasks::TokenId).uuid().not_null())
|
||||
|
||||
@@ -18,7 +18,11 @@ impl MigrationTrait for Migration {
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessVariables::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(ProcessVariables::InstanceId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessVariables::InstanceId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessVariables::Name).string().not_null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessVariables::VarType)
|
||||
@@ -27,8 +31,16 @@ impl MigrationTrait for Migration {
|
||||
.default("string"),
|
||||
)
|
||||
.col(ColumnDef::new(ProcessVariables::ValueString).text().null())
|
||||
.col(ColumnDef::new(ProcessVariables::ValueNumber).double().null())
|
||||
.col(ColumnDef::new(ProcessVariables::ValueBoolean).boolean().null())
|
||||
.col(
|
||||
ColumnDef::new(ProcessVariables::ValueNumber)
|
||||
.double()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessVariables::ValueBoolean)
|
||||
.boolean()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ProcessVariables::ValueDate)
|
||||
.timestamp_with_time_zone()
|
||||
|
||||
@@ -18,16 +18,8 @@ impl MigrationTrait for Migration {
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(MessageTemplates::TenantId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::Name)
|
||||
.string()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::Code)
|
||||
.string()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(MessageTemplates::Name).string().not_null())
|
||||
.col(ColumnDef::new(MessageTemplates::Code).string().not_null())
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::Channel)
|
||||
.string()
|
||||
@@ -50,11 +42,31 @@ impl MigrationTrait for Migration {
|
||||
.not_null()
|
||||
.default("zh-CN"),
|
||||
)
|
||||
.col(ColumnDef::new(MessageTemplates::CreatedAt).timestamp_with_time_zone().not_null())
|
||||
.col(ColumnDef::new(MessageTemplates::UpdatedAt).timestamp_with_time_zone().not_null())
|
||||
.col(ColumnDef::new(MessageTemplates::CreatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(MessageTemplates::UpdatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(MessageTemplates::DeletedAt).timestamp_with_time_zone().null())
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::CreatedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::UpdatedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::CreatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::UpdatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageTemplates::DeletedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.null(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -11,12 +11,7 @@ impl MigrationTrait for Migration {
|
||||
Table::create()
|
||||
.table(Messages::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Messages::Id)
|
||||
.uuid()
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(Messages::Id).uuid().not_null().primary_key())
|
||||
.col(ColumnDef::new(Messages::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(Messages::TemplateId).uuid().null())
|
||||
.col(ColumnDef::new(Messages::SenderId).uuid().null())
|
||||
@@ -49,26 +44,50 @@ impl MigrationTrait for Migration {
|
||||
.not_null()
|
||||
.default(false),
|
||||
)
|
||||
.col(ColumnDef::new(Messages::ReadAt).timestamp_with_time_zone().null())
|
||||
.col(
|
||||
ColumnDef::new(Messages::ReadAt)
|
||||
.timestamp_with_time_zone()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Messages::IsArchived)
|
||||
.boolean()
|
||||
.not_null()
|
||||
.default(false),
|
||||
)
|
||||
.col(ColumnDef::new(Messages::ArchivedAt).timestamp_with_time_zone().null())
|
||||
.col(ColumnDef::new(Messages::SentAt).timestamp_with_time_zone().null())
|
||||
.col(
|
||||
ColumnDef::new(Messages::ArchivedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Messages::SentAt)
|
||||
.timestamp_with_time_zone()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Messages::Status)
|
||||
.string()
|
||||
.not_null()
|
||||
.default("sent"),
|
||||
)
|
||||
.col(ColumnDef::new(Messages::CreatedAt).timestamp_with_time_zone().not_null())
|
||||
.col(ColumnDef::new(Messages::UpdatedAt).timestamp_with_time_zone().not_null())
|
||||
.col(
|
||||
ColumnDef::new(Messages::CreatedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Messages::UpdatedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Messages::CreatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(Messages::UpdatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(Messages::DeletedAt).timestamp_with_time_zone().null())
|
||||
.col(
|
||||
ColumnDef::new(Messages::DeletedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.null(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -17,23 +17,63 @@ impl MigrationTrait for Migration {
|
||||
.not_null()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(MessageSubscriptions::TenantId).uuid().not_null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::UserId).uuid().not_null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::NotificationTypes).json().null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::ChannelPreferences).json().null())
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::TenantId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::UserId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::NotificationTypes)
|
||||
.json()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::ChannelPreferences)
|
||||
.json()
|
||||
.null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::DndEnabled)
|
||||
.boolean()
|
||||
.not_null()
|
||||
.default(false),
|
||||
)
|
||||
.col(ColumnDef::new(MessageSubscriptions::DndStart).string().null())
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::DndStart)
|
||||
.string()
|
||||
.null(),
|
||||
)
|
||||
.col(ColumnDef::new(MessageSubscriptions::DndEnd).string().null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::CreatedAt).timestamp_with_time_zone().not_null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::UpdatedAt).timestamp_with_time_zone().not_null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::CreatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::UpdatedBy).uuid().not_null())
|
||||
.col(ColumnDef::new(MessageSubscriptions::DeletedAt).timestamp_with_time_zone().null())
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::CreatedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::UpdatedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::CreatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::UpdatedBy)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(MessageSubscriptions::DeletedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.null(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -26,20 +26,33 @@ impl MigrationTrait for Migration {
|
||||
.col(ColumnDef::new(AuditLogs::NewValue).json().null())
|
||||
.col(ColumnDef::new(AuditLogs::IpAddress).string().null())
|
||||
.col(ColumnDef::new(AuditLogs::UserAgent).text().null())
|
||||
.col(ColumnDef::new(AuditLogs::CreatedAt).timestamp_with_time_zone().not_null())
|
||||
.col(
|
||||
ColumnDef::new(AuditLogs::CreatedAt)
|
||||
.timestamp_with_time_zone()
|
||||
.not_null(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager.get_connection().execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"CREATE INDEX idx_audit_logs_tenant ON audit_logs (tenant_id)".to_string(),
|
||||
)).await.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
manager
|
||||
.get_connection()
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"CREATE INDEX idx_audit_logs_tenant ON audit_logs (tenant_id)".to_string(),
|
||||
))
|
||||
.await
|
||||
.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
|
||||
manager.get_connection().execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"CREATE INDEX idx_audit_logs_resource ON audit_logs (resource_type, resource_id)".to_string(),
|
||||
)).await.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
manager
|
||||
.get_connection()
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"CREATE INDEX idx_audit_logs_resource ON audit_logs (resource_type, resource_id)"
|
||||
.to_string(),
|
||||
))
|
||||
.await
|
||||
.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
use sea_orm::Statement;
|
||||
use sea_orm::DatabaseBackend;
|
||||
use sea_orm::Statement;
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
/// Recreate unique indexes on roles and permissions to include soft-delete awareness.
|
||||
#[derive(DeriveMigrationName)]
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
/// 修复 settings 表唯一索引:原索引使用 scope_id 列,当 scope_id 为 NULL 时
|
||||
/// PostgreSQL B-tree 不认为两行重复(NULL != NULL),导致可插入重复数据。
|
||||
/// 修复方案:使用 COALESCE(scope_id, '00000000-0000-0000-0000-000000000000')
|
||||
/// 将 NULL 转为固定 UUID,使索引能正确约束 NULL scope_id 的行。
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// 删除旧索引
|
||||
manager
|
||||
.get_connection()
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"DROP INDEX IF EXISTS idx_settings_scope_key".to_string(),
|
||||
))
|
||||
.await
|
||||
.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
|
||||
// 创建新索引,使用 COALESCE 处理 NULL scope_id
|
||||
manager.get_connection().execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"CREATE UNIQUE INDEX idx_settings_scope_key ON settings (tenant_id, scope, COALESCE(scope_id, '00000000-0000-0000-0000-000000000000'), setting_key) WHERE deleted_at IS NULL".to_string(),
|
||||
)).await.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
|
||||
// 清理可能已存在的重复数据(保留每组最新的一条)
|
||||
manager.get_connection().execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
r#"
|
||||
DELETE FROM settings a USING settings b
|
||||
WHERE a.id < b.id
|
||||
AND a.tenant_id = b.tenant_id
|
||||
AND a.scope = b.scope
|
||||
AND a.setting_key = b.setting_key
|
||||
AND a.deleted_at IS NULL
|
||||
AND b.deleted_at IS NULL
|
||||
AND COALESCE(a.scope_id, '00000000-0000-0000-0000-000000000000') = COALESCE(b.scope_id, '00000000-0000-0000-0000-000000000000')
|
||||
"#.to_string(),
|
||||
)).await.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// 回滚:删除新索引,恢复旧索引
|
||||
manager
|
||||
.get_connection()
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"DROP INDEX IF EXISTS idx_settings_scope_key".to_string(),
|
||||
))
|
||||
.await
|
||||
.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
|
||||
manager.get_connection().execute(sea_orm::Statement::from_string(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"CREATE UNIQUE INDEX idx_settings_scope_key ON settings (tenant_id, scope, scope_id, setting_key) WHERE deleted_at IS NULL".to_string(),
|
||||
)).await.map_err(|e| DbErr::Custom(e.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,11 @@ impl MigrationTrait for Migration {
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(Alias::new("tenant_id")).uuid().not_null())
|
||||
.col(ColumnDef::new(Alias::new("event_type")).string_len(200).not_null())
|
||||
.col(
|
||||
ColumnDef::new(Alias::new("event_type"))
|
||||
.string_len(200)
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Alias::new("payload")).json().null())
|
||||
.col(ColumnDef::new(Alias::new("correlation_id")).uuid().null())
|
||||
.col(
|
||||
|
||||
Reference in New Issue
Block a user