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

@@ -1,10 +1,10 @@
pub mod department;
pub mod organization;
pub mod permission;
pub mod position;
pub mod role;
pub mod role_permission;
pub mod user;
pub mod user_credential;
pub mod user_token;
pub mod role;
pub mod permission;
pub mod role_permission;
pub mod user_role;
pub mod organization;
pub mod department;
pub mod position;
pub mod user_token;

View File

@@ -66,12 +66,7 @@ where
refresh_ttl_secs: state.refresh_ttl_secs,
};
let resp = AuthService::refresh(
&req.refresh_token,
&state.db,
&jwt_config,
)
.await?;
let resp = AuthService::refresh(&req.refresh_token, &state.db, &jwt_config).await?;
Ok(Json(ApiResponse::ok(resp)))
}

View File

@@ -12,10 +12,10 @@ use crate::dto::{
CreateDepartmentReq, CreateOrganizationReq, CreatePositionReq, DepartmentResp,
OrganizationResp, PositionResp, UpdateDepartmentReq, UpdateOrganizationReq, UpdatePositionReq,
};
use erp_core::rbac::require_permission;
use crate::service::dept_service::DeptService;
use crate::service::org_service::OrgService;
use crate::service::position_service::PositionService;
use erp_core::rbac::require_permission;
// --- Organization handlers ---
@@ -180,14 +180,7 @@ where
{
require_permission(&ctx, "department.update")?;
let dept = DeptService::update(
id,
ctx.tenant_id,
ctx.user_id,
&req,
&state.db,
)
.await?;
let dept = DeptService::update(id, ctx.tenant_id, ctx.user_id, &req, &state.db).await?;
Ok(Json(ApiResponse::ok(dept)))
}
@@ -284,14 +277,7 @@ where
{
require_permission(&ctx, "position.update")?;
let pos = PositionService::update(
id,
ctx.tenant_id,
ctx.user_id,
&req,
&state.db,
)
.await?;
let pos = PositionService::update(id, ctx.tenant_id, ctx.user_id, &req, &state.db).await?;
Ok(Json(ApiResponse::ok(pos)))
}

View File

@@ -9,9 +9,9 @@ use uuid::Uuid;
use crate::auth_state::AuthState;
use crate::dto::{AssignPermissionsReq, CreateRoleReq, PermissionResp, RoleResp, UpdateRoleReq};
use erp_core::rbac::require_permission;
use crate::service::permission_service::PermissionService;
use crate::service::role_service::RoleService;
use erp_core::rbac::require_permission;
/// GET /api/v1/roles
///

View File

@@ -10,8 +10,8 @@ use uuid::Uuid;
use crate::auth_state::AuthState;
use crate::dto::{CreateUserReq, RoleResp, UpdateUserReq, UserResp};
use erp_core::rbac::require_permission;
use crate::service::user_service::UserService;
use erp_core::rbac::require_permission;
/// Query parameters for user list endpoint.
#[derive(Debug, Deserialize)]
@@ -41,9 +41,13 @@ where
page: params.page,
page_size: params.page_size,
};
let (users, total) =
UserService::list(ctx.tenant_id, &pagination, params.search.as_deref(), &state.db)
.await?;
let (users, total) = UserService::list(
ctx.tenant_id,
&pagination,
params.search.as_deref(),
&state.db,
)
.await?;
let page = pagination.page.unwrap_or(1);
let page_size = pagination.limit();
@@ -123,8 +127,7 @@ where
{
require_permission(&ctx, "user.update")?;
let user =
UserService::update(id, ctx.tenant_id, ctx.user_id, &req, &state.db).await?;
let user = UserService::update(id, ctx.tenant_id, ctx.user_id, &req, &state.db).await?;
Ok(Json(ApiResponse::ok(user)))
}
@@ -181,8 +184,7 @@ where
require_permission(&ctx, "user.update")?;
let roles =
UserService::assign_roles(id, ctx.tenant_id, ctx.user_id, &req.role_ids, &state.db)
.await?;
UserService::assign_roles(id, ctx.tenant_id, ctx.user_id, &req.role_ids, &state.db).await?;
Ok(Json(ApiResponse::ok(AssignRolesResp { roles })))
}

View File

@@ -39,8 +39,8 @@ pub async fn jwt_auth_middleware_fn(
.strip_prefix("Bearer ")
.ok_or(AppError::Unauthorized)?;
let claims = TokenService::decode_token(token, &jwt_secret)
.map_err(|_| AppError::Unauthorized)?;
let claims =
TokenService::decode_token(token, &jwt_secret).map_err(|_| AppError::Unauthorized)?;
// Verify this is an access token, not a refresh token
if claims.token_type != "access" {

View File

@@ -1,4 +1,4 @@
pub mod jwt_auth;
pub use jwt_auth::jwt_auth_middleware_fn;
pub use erp_core::rbac::{require_any_permission, require_permission, require_role};
pub use jwt_auth::jwt_auth_middleware_fn;

View File

@@ -101,8 +101,7 @@ impl AuthModule {
// Position routes (nested under department)
.route(
"/departments/{dept_id}/positions",
axum::routing::get(org_handler::list_positions)
.post(org_handler::create_position),
axum::routing::get(org_handler::list_positions).post(org_handler::create_position),
)
.route(
"/positions/{id}",

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(