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:
iven
2026-04-15 00:49:20 +08:00
parent e16c1a85d7
commit 9568dd7875
113 changed files with 4355 additions and 937 deletions

View File

@@ -79,10 +79,8 @@ impl AuthService {
}
// 5. Get roles and permissions
let roles: Vec<String> =
TokenService::get_user_roles(user_model.id, tenant_id, db).await?;
let permissions =
TokenService::get_user_permissions(user_model.id, tenant_id, db).await?;
let roles: Vec<String> = TokenService::get_user_roles(user_model.id, tenant_id, db).await?;
let permissions = TokenService::get_user_permissions(user_model.id, tenant_id, db).await?;
// 6. Sign tokens
let access_token = TokenService::sign_access_token(
@@ -154,10 +152,8 @@ impl AuthService {
TokenService::revoke_token(old_token_id, db).await?;
// Fetch fresh roles and permissions
let roles: Vec<String> =
TokenService::get_user_roles(claims.sub, claims.tid, db).await?;
let permissions =
TokenService::get_user_permissions(claims.sub, claims.tid, db).await?;
let roles: Vec<String> = TokenService::get_user_roles(claims.sub, claims.tid, db).await?;
let permissions = TokenService::get_user_permissions(claims.sub, claims.tid, db).await?;
// Sign new token pair
let access_token = TokenService::sign_access_token(

View File

@@ -85,7 +85,9 @@ impl DeptService {
.one(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?
.filter(|d| d.tenant_id == tenant_id && d.org_id == org_id && d.deleted_at.is_none())
.filter(|d| {
d.tenant_id == tenant_id && d.org_id == org_id && d.deleted_at.is_none()
})
.ok_or_else(|| AuthError::Validation("父级部门不存在".to_string()))?;
let parent_path = parent.path.clone().unwrap_or_default();
@@ -120,15 +122,25 @@ impl DeptService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"department.created",
tenant_id,
serde_json::json!({ "dept_id": id, "org_id": org_id, "name": req.name }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"department.created",
tenant_id,
serde_json::json!({ "dept_id": id, "org_id": org_id, "name": req.name }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "department.create", "department")
.with_resource_id(id),
AuditLog::new(
tenant_id,
Some(operator_id),
"department.create",
"department",
)
.with_resource_id(id),
db,
)
.await;
@@ -205,8 +217,13 @@ impl DeptService {
.map_err(|e| AuthError::Validation(e.to_string()))?;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "department.update", "department")
.with_resource_id(id),
AuditLog::new(
tenant_id,
Some(operator_id),
"department.update",
"department",
)
.with_resource_id(id),
db,
)
.await;
@@ -267,15 +284,25 @@ impl DeptService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"department.deleted",
tenant_id,
serde_json::json!({ "dept_id": id }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"department.deleted",
tenant_id,
serde_json::json!({ "dept_id": id }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "department.delete", "department")
.with_resource_id(id),
AuditLog::new(
tenant_id,
Some(operator_id),
"department.delete",
"department",
)
.with_resource_id(id),
db,
)
.await;

View File

@@ -106,15 +106,25 @@ impl OrgService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"organization.created",
tenant_id,
serde_json::json!({ "org_id": id, "name": req.name }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"organization.created",
tenant_id,
serde_json::json!({ "org_id": id, "name": req.name }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "organization.create", "organization")
.with_resource_id(id),
AuditLog::new(
tenant_id,
Some(operator_id),
"organization.create",
"organization",
)
.with_resource_id(id),
db,
)
.await;
@@ -187,8 +197,13 @@ impl OrgService {
.map_err(|e| AuthError::Validation(e.to_string()))?;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "organization.update", "organization")
.with_resource_id(id),
AuditLog::new(
tenant_id,
Some(operator_id),
"organization.update",
"organization",
)
.with_resource_id(id),
db,
)
.await;
@@ -246,15 +261,25 @@ impl OrgService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"organization.deleted",
tenant_id,
serde_json::json!({ "org_id": id }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"organization.deleted",
tenant_id,
serde_json::json!({ "org_id": id }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "organization.delete", "organization")
.with_resource_id(id),
AuditLog::new(
tenant_id,
Some(operator_id),
"organization.delete",
"organization",
)
.with_resource_id(id),
db,
)
.await;

View File

@@ -1,6 +1,6 @@
use argon2::{
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
Argon2,
password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString, rand_core::OsRng},
};
use crate::error::{AuthError, AuthResult};

View File

@@ -105,11 +105,16 @@ impl PositionService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"position.created",
tenant_id,
serde_json::json!({ "position_id": id, "dept_id": dept_id, "name": req.name }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"position.created",
tenant_id,
serde_json::json!({ "position_id": id, "dept_id": dept_id, "name": req.name }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "position.create", "position")
@@ -230,11 +235,16 @@ impl PositionService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"position.deleted",
tenant_id,
serde_json::json!({ "position_id": id }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"position.deleted",
tenant_id,
serde_json::json!({ "position_id": id }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "position.delete", "position")

View File

@@ -1,7 +1,5 @@
use chrono::Utc;
use sea_orm::{
ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set,
};
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set};
use uuid::Uuid;
use crate::dto::{PermissionResp, RoleResp};
@@ -127,15 +125,19 @@ impl RoleService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"role.created",
tenant_id,
serde_json::json!({ "role_id": id, "code": code }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"role.created",
tenant_id,
serde_json::json!({ "role_id": id, "code": code }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "role.create", "role")
.with_resource_id(id),
AuditLog::new(tenant_id, Some(operator_id), "role.create", "role").with_resource_id(id),
db,
)
.await;
@@ -190,8 +192,7 @@ impl RoleService {
.map_err(|e| AuthError::Validation(e.to_string()))?;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "role.update", "role")
.with_resource_id(id),
AuditLog::new(tenant_id, Some(operator_id), "role.update", "role").with_resource_id(id),
db,
)
.await;
@@ -238,15 +239,19 @@ impl RoleService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"role.deleted",
tenant_id,
serde_json::json!({ "role_id": id }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"role.deleted",
tenant_id,
serde_json::json!({ "role_id": id }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "role.delete", "role")
.with_resource_id(id),
AuditLog::new(tenant_id, Some(operator_id), "role.delete", "role").with_resource_id(id),
db,
)
.await;

View File

@@ -22,52 +22,286 @@ const DEFAULT_PERMISSIONS: &[(&str, &str, &str, &str, &str)] = &[
("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", "删除岗位"),
(
"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", "删除数据字典"),
(
"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", "生成文档编号"),
(
"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", "编辑语言设置"),
(
"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", "委派流程任务"),
(
"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.list",
"查看消息",
"message",
"list",
"查看消息列表",
),
("message.send", "发送消息", "message", "send", "发送新消息"),
("message.template.list", "查看消息模板", "message.template", "list", "查看消息模板列表"),
("message.template.create", "创建消息模板", "message.template", "create", "创建消息模板"),
(
"message.template.list",
"查看消息模板",
"message.template",
"list",
"查看消息模板列表",
),
(
"message.template.create",
"创建消息模板",
"message.template",
"create",
"创建消息模板",
),
];
/// Indices of read-only (list/read) permissions within DEFAULT_PERMISSIONS.
@@ -128,7 +362,9 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
perm.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
perm.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
}
// 2. Create "admin" role with all permissions
@@ -147,7 +383,10 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
admin_role.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
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 {
@@ -162,7 +401,9 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
rp.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
rp.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
}
// 3. Create "viewer" role with read-only permissions
@@ -181,7 +422,10 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
viewer_role.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
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 {
@@ -197,7 +441,9 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
rp.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
rp.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
}
}
@@ -222,7 +468,10 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
admin_user.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
admin_user
.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
// Create password credential for admin user
let cred = user_credential::ActiveModel {
@@ -239,7 +488,9 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
cred.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
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 {
@@ -253,7 +504,10 @@ pub async fn seed_tenant_auth(
deleted_at: Set(None),
version: Set(1),
};
user_role_assignment.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
user_role_assignment
.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
tracing::info!(
tenant_id = %tenant_id,

View File

@@ -84,17 +84,21 @@ impl UserService {
deleted_at: Set(None),
version: Set(1),
};
cred
.insert(db)
cred.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
// Publish domain event
event_bus.publish(erp_core::events::DomainEvent::new(
"user.created",
tenant_id,
serde_json::json!({ "user_id": user_id, "username": req.username }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"user.created",
tenant_id,
serde_json::json!({ "user_id": user_id, "username": req.username }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "user.create", "user")
@@ -147,11 +151,11 @@ impl UserService {
.filter(user::Column::TenantId.eq(tenant_id))
.filter(user::Column::DeletedAt.is_null());
if let Some(term) = search && !term.is_empty() {
if let Some(term) = search
&& !term.is_empty()
{
use sea_orm::sea_query::Expr;
query = query.filter(
Expr::col(user::Column::Username).like(format!("%{}%", term)),
);
query = query.filter(Expr::col(user::Column::Username).like(format!("%{}%", term)));
}
let paginator = query.paginate(db, pagination.limit());
@@ -225,8 +229,7 @@ impl UserService {
.map_err(|e| AuthError::Validation(e.to_string()))?;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "user.update", "user")
.with_resource_id(id),
AuditLog::new(tenant_id, Some(operator_id), "user.update", "user").with_resource_id(id),
db,
)
.await;
@@ -261,15 +264,19 @@ impl UserService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
event_bus.publish(erp_core::events::DomainEvent::new(
"user.deleted",
tenant_id,
serde_json::json!({ "user_id": id }),
), db).await;
event_bus
.publish(
erp_core::events::DomainEvent::new(
"user.deleted",
tenant_id,
serde_json::json!({ "user_id": id }),
),
db,
)
.await;
audit_service::record(
AuditLog::new(tenant_id, Some(operator_id), "user.delete", "user")
.with_resource_id(id),
AuditLog::new(tenant_id, Some(operator_id), "user.delete", "user").with_resource_id(id),
db,
)
.await;
@@ -302,7 +309,9 @@ impl UserService {
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
if found.len() != role_ids.len() {
return Err(AuthError::Validation("部分角色不存在或不属于当前租户".to_string()));
return Err(AuthError::Validation(
"部分角色不存在或不属于当前租户".to_string(),
));
}
}
@@ -328,7 +337,10 @@ impl UserService {
deleted_at: Set(None),
version: Set(1),
};
assignment.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
assignment
.insert(db)
.await
.map_err(|e| AuthError::Validation(e.to_string()))?;
}
audit_service::record(