feat(core): add audit logging to all mutation operations
Create audit_log SeaORM entity and audit_service::record() helper. Integrate audit recording into 35 mutation endpoints across all modules: - erp-auth: user/role/organization/department/position CRUD (15 actions) - erp-config: dictionary/menu/setting/numbering_rule CRUD (15 actions) - erp-workflow: definition/instance/task operations (8 actions) - erp-message: send/system/mark_read/delete (5 actions) Uses fire-and-forget pattern — audit failures logged but non-blocking.
This commit is contained in:
@@ -10,6 +10,8 @@ use crate::dto::{
|
||||
use crate::engine::parser;
|
||||
use crate::entity::process_definition;
|
||||
use crate::error::{WorkflowError, WorkflowResult};
|
||||
use erp_core::audit::AuditLog;
|
||||
use erp_core::audit_service;
|
||||
use erp_core::error::check_version;
|
||||
use erp_core::events::EventBus;
|
||||
use erp_core::types::Pagination;
|
||||
@@ -107,6 +109,13 @@ impl DefinitionService {
|
||||
serde_json::json!({ "definition_id": id, "key": req.key }),
|
||||
));
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "process_definition.create", "process_definition")
|
||||
.with_resource_id(id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(ProcessDefinitionResp {
|
||||
id,
|
||||
name: req.name.clone(),
|
||||
@@ -182,6 +191,13 @@ impl DefinitionService {
|
||||
.await
|
||||
.map_err(|e| WorkflowError::Validation(e.to_string()))?;
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "process_definition.update", "process_definition")
|
||||
.with_resource_id(id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(Self::model_to_resp(&updated))
|
||||
}
|
||||
|
||||
@@ -231,6 +247,13 @@ impl DefinitionService {
|
||||
serde_json::json!({ "definition_id": id }),
|
||||
));
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "process_definition.publish", "process_definition")
|
||||
.with_resource_id(id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(Self::model_to_resp(&updated))
|
||||
}
|
||||
|
||||
@@ -259,6 +282,13 @@ impl DefinitionService {
|
||||
.await
|
||||
.map_err(|e| WorkflowError::Validation(e.to_string()))?;
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "process_definition.delete", "process_definition")
|
||||
.with_resource_id(id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ use crate::engine::executor::FlowExecutor;
|
||||
use crate::engine::parser;
|
||||
use crate::entity::{process_definition, process_instance, process_variable, token};
|
||||
use crate::error::{WorkflowError, WorkflowResult};
|
||||
use erp_core::audit::AuditLog;
|
||||
use erp_core::audit_service;
|
||||
use erp_core::events::EventBus;
|
||||
use erp_core::types::Pagination;
|
||||
|
||||
@@ -130,6 +132,13 @@ impl InstanceService {
|
||||
serde_json::json!({ "instance_id": instance_id, "definition_id": definition.id, "started_by": operator_id }),
|
||||
));
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "process_instance.start", "process_instance")
|
||||
.with_resource_id(instance_id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
// 查询创建后的实例(包含 token)
|
||||
let instance = process_instance::Entity::find_by_id(instance_id)
|
||||
.one(db)
|
||||
@@ -303,6 +312,14 @@ impl InstanceService {
|
||||
.await
|
||||
.map_err(|e| WorkflowError::Validation(e.to_string()))?;
|
||||
|
||||
let action = format!("process_instance.{}", to_status);
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), action, "process_instance")
|
||||
.with_resource_id(id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ use crate::engine::executor::FlowExecutor;
|
||||
use crate::engine::parser;
|
||||
use crate::entity::{process_definition, process_instance, task};
|
||||
use crate::error::{WorkflowError, WorkflowResult};
|
||||
use erp_core::audit::AuditLog;
|
||||
use erp_core::audit_service;
|
||||
use erp_core::events::EventBus;
|
||||
use erp_core::types::Pagination;
|
||||
|
||||
@@ -242,6 +244,13 @@ impl TaskService {
|
||||
serde_json::json!({ "task_id": id, "outcome": req.outcome }),
|
||||
));
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "task.complete", "task")
|
||||
.with_resource_id(id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
// 重新查询任务
|
||||
let updated = task::Entity::find_by_id(id)
|
||||
.one(db)
|
||||
@@ -311,6 +320,13 @@ impl TaskService {
|
||||
.await
|
||||
.map_err(|e| WorkflowError::Validation(e.to_string()))?;
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "task.delegate", "task")
|
||||
.with_resource_id(id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(Self::model_to_resp(&updated))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user