Files
erp/crates/erp-auth/src/service/seed.rs
iven 9568dd7875 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)
2026-04-15 00:49:20 +08:00

521 lines
14 KiB
Rust

use sea_orm::{ActiveModelTrait, Set};
use uuid::Uuid;
use crate::entity::{permission, role, role_permission, user, user_credential, user_role};
use crate::error::AuthError;
use super::password;
/// Permission definitions to seed for every new tenant.
/// Each tuple is: (code, name, resource, action, description)
///
/// 编码使用点分隔 (`resource.action`),与 handler 中的 `require_permission` 调用保持一致。
const DEFAULT_PERMISSIONS: &[(&str, &str, &str, &str, &str)] = &[
// === Auth module ===
("user.list", "查看用户列表", "user", "list", "查看用户列表"),
("user.create", "创建用户", "user", "create", "创建新用户"),
("user.read", "查看用户详情", "user", "read", "查看用户信息"),
("user.update", "编辑用户", "user", "update", "编辑用户信息"),
("user.delete", "删除用户", "user", "delete", "软删除用户"),
("role.list", "查看角色列表", "role", "list", "查看角色列表"),
("role.create", "创建角色", "role", "create", "创建新角色"),
("role.read", "查看角色详情", "role", "read", "查看角色信息"),
("role.update", "编辑角色", "role", "update", "编辑角色"),
("role.delete", "删除角色", "role", "delete", "删除角色"),
(
"permission.list",
"查看权限",
"permission",
"list",
"查看权限列表",
),
(
"organization.list",
"查看组织列表",
"organization",
"list",
"查看组织列表",
),
(
"organization.create",
"创建组织",
"organization",
"create",
"创建组织",
),
(
"organization.update",
"编辑组织",
"organization",
"update",
"编辑组织",
),
(
"organization.delete",
"删除组织",
"organization",
"delete",
"删除组织",
),
(
"department.list",
"查看部门列表",
"department",
"list",
"查看部门列表",
),
(
"department.create",
"创建部门",
"department",
"create",
"创建部门",
),
(
"department.update",
"编辑部门",
"department",
"update",
"编辑部门",
),
(
"department.delete",
"删除部门",
"department",
"delete",
"删除部门",
),
(
"position.list",
"查看岗位列表",
"position",
"list",
"查看岗位列表",
),
(
"position.create",
"创建岗位",
"position",
"create",
"创建岗位",
),
(
"position.update",
"编辑岗位",
"position",
"update",
"编辑岗位",
),
(
"position.delete",
"删除岗位",
"position",
"delete",
"删除岗位",
),
// === Config module ===
(
"dictionary.list",
"查看字典",
"dictionary",
"list",
"查看数据字典",
),
(
"dictionary.create",
"创建字典",
"dictionary",
"create",
"创建数据字典",
),
(
"dictionary.update",
"编辑字典",
"dictionary",
"update",
"编辑数据字典",
),
(
"dictionary.delete",
"删除字典",
"dictionary",
"delete",
"删除数据字典",
),
("menu.list", "查看菜单", "menu", "list", "查看菜单配置"),
("menu.update", "编辑菜单", "menu", "update", "编辑菜单配置"),
(
"setting.read",
"查看配置",
"setting",
"read",
"查看系统参数",
),
(
"setting.update",
"编辑配置",
"setting",
"update",
"编辑系统参数",
),
(
"setting.delete",
"删除配置",
"setting",
"delete",
"删除系统参数",
),
(
"numbering.list",
"查看编号规则",
"numbering",
"list",
"查看编号规则",
),
(
"numbering.create",
"创建编号规则",
"numbering",
"create",
"创建编号规则",
),
(
"numbering.update",
"编辑编号规则",
"numbering",
"update",
"编辑编号规则",
),
(
"numbering.delete",
"删除编号规则",
"numbering",
"delete",
"删除编号规则",
),
(
"numbering.generate",
"生成编号",
"numbering",
"generate",
"生成文档编号",
),
("theme.read", "查看主题", "theme", "read", "查看主题设置"),
(
"theme.update",
"编辑主题",
"theme",
"update",
"编辑主题设置",
),
(
"language.list",
"查看语言",
"language",
"list",
"查看语言配置",
),
(
"language.update",
"编辑语言",
"language",
"update",
"编辑语言设置",
),
// === Workflow module ===
(
"workflow.create",
"创建流程",
"workflow",
"create",
"创建流程定义",
),
(
"workflow.list",
"查看流程",
"workflow",
"list",
"查看流程列表",
),
(
"workflow.read",
"查看流程详情",
"workflow",
"read",
"查看流程定义详情",
),
(
"workflow.update",
"编辑流程",
"workflow",
"update",
"编辑流程定义",
),
(
"workflow.publish",
"发布流程",
"workflow",
"publish",
"发布流程定义",
),
(
"workflow.start",
"发起流程",
"workflow",
"start",
"发起流程实例",
),
(
"workflow.approve",
"审批任务",
"workflow",
"approve",
"审批流程任务",
),
(
"workflow.delegate",
"委派任务",
"workflow",
"delegate",
"委派流程任务",
),
// === Message module ===
(
"message.list",
"查看消息",
"message",
"list",
"查看消息列表",
),
("message.send", "发送消息", "message", "send", "发送新消息"),
(
"message.template.list",
"查看消息模板",
"message.template",
"list",
"查看消息模板列表",
),
(
"message.template.create",
"创建消息模板",
"message.template",
"create",
"创建消息模板",
),
];
/// Indices of read-only (list/read) permissions within DEFAULT_PERMISSIONS.
const READ_PERM_INDICES: &[usize] = &[
0, // user.list
2, // user.read
5, // role.list
7, // role.read
10, // permission.list
11, // organization.list
15, // department.list
19, // position.list
23, // dictionary.list
28, // menu.list
30, // setting.read
32, // numbering.list
37, // theme.read
39, // language.list
43, // workflow.list
44, // workflow.read
49, // message.list
51, // message.template.list
];
/// Seed default auth data for a new tenant.
///
/// Creates:
/// - 53 permissions covering auth/config/workflow/message modules
/// - An "admin" system role with all permissions
/// - A "viewer" system role with read-only permissions
/// - A super-admin user with the admin role and a password credential
pub async fn seed_tenant_auth(
db: &sea_orm::DatabaseConnection,
tenant_id: Uuid,
super_admin_password: &str,
) -> Result<(), AuthError> {
let now = chrono::Utc::now();
let system_user_id = Uuid::nil();
// 1. Create permissions
let mut perm_ids: Vec<Uuid> = Vec::with_capacity(DEFAULT_PERMISSIONS.len());
for (code, name, resource, action, desc) in DEFAULT_PERMISSIONS {
let perm_id = Uuid::now_v7();
perm_ids.push(perm_id);
let perm = permission::ActiveModel {
id: Set(perm_id),
tenant_id: Set(tenant_id),
code: Set(code.to_string()),
name: Set(name.to_string()),
resource: Set(resource.to_string()),
action: Set(action.to_string()),
description: Set(Some(desc.to_string())),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
perm.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
}
// 2. Create "admin" role with all permissions
let admin_role_id = Uuid::now_v7();
let admin_role = role::ActiveModel {
id: Set(admin_role_id),
tenant_id: Set(tenant_id),
name: Set("管理员".to_string()),
code: Set("admin".to_string()),
description: Set(Some("系统管理员,拥有所有权限".to_string())),
is_system: Set(true),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
admin_role
.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
// Assign all permissions to admin role
for perm_id in &perm_ids {
let rp = role_permission::ActiveModel {
role_id: Set(admin_role_id),
permission_id: Set(*perm_id),
tenant_id: Set(tenant_id),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
rp.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
}
// 3. Create "viewer" role with read-only permissions
let viewer_role_id = Uuid::now_v7();
let viewer_role = role::ActiveModel {
id: Set(viewer_role_id),
tenant_id: Set(tenant_id),
name: Set("查看者".to_string()),
code: Set("viewer".to_string()),
description: Set(Some("只读用户,可查看所有数据".to_string())),
is_system: Set(true),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
viewer_role
.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
// Assign read permissions to viewer role
for idx in READ_PERM_INDICES {
if *idx < perm_ids.len() {
let rp = role_permission::ActiveModel {
role_id: Set(viewer_role_id),
permission_id: Set(perm_ids[*idx]),
tenant_id: Set(tenant_id),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
rp.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
}
}
// 4. Create super admin user
let admin_user_id = Uuid::now_v7();
let password_hash = password::hash_password(super_admin_password)?;
let admin_user = user::ActiveModel {
id: Set(admin_user_id),
tenant_id: Set(tenant_id),
username: Set("admin".to_string()),
email: Set(None),
phone: Set(None),
display_name: Set(Some("系统管理员".to_string())),
avatar_url: Set(None),
status: Set("active".to_string()),
last_login_at: Set(None),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
admin_user
.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
// Create password credential for admin user
let cred = user_credential::ActiveModel {
id: Set(Uuid::now_v7()),
tenant_id: Set(tenant_id),
user_id: Set(admin_user_id),
credential_type: Set("password".to_string()),
credential_data: Set(Some(serde_json::json!({ "hash": password_hash }))),
verified: Set(true),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
cred.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
// 5. Assign admin role to admin user
let user_role_assignment = user_role::ActiveModel {
user_id: Set(admin_user_id),
role_id: Set(admin_role_id),
tenant_id: Set(tenant_id),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(system_user_id),
updated_by: Set(system_user_id),
deleted_at: Set(None),
version: Set(1),
};
user_role_assignment
.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
tracing::info!(
tenant_id = %tenant_id,
admin_user_id = %admin_user_id,
"Seeded tenant auth: admin user, 2 roles, {} permissions",
DEFAULT_PERMISSIONS.len()
);
Ok(())
}