fix(workflow): add tenant membership check to task delegation
The delegate method was accepting any UUID as delegate_to without verifying the target user belongs to the same tenant. This allowed cross-tenant task delegation. Added raw SQL check against users table to avoid cross-module dependency on erp-auth.
This commit is contained in:
@@ -2,8 +2,8 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set,
|
ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseBackend, EntityTrait,
|
||||||
TransactionTrait,
|
PaginatorTrait, QueryFilter, Set, Statement, TransactionTrait,
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -278,6 +278,25 @@ impl TaskService {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证目标用户属于同一租户(使用 raw SQL 避免跨模块依赖 erp-auth)
|
||||||
|
let result = db.query_one(Statement::from_sql_and_values(
|
||||||
|
DatabaseBackend::Postgres,
|
||||||
|
"SELECT EXISTS(SELECT 1 FROM users WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL AND status = 'active') AS ok",
|
||||||
|
[req.delegate_to.into(), tenant_id.into()],
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.map_err(|e| WorkflowError::Validation(e.to_string()))?;
|
||||||
|
|
||||||
|
let target_ok = result
|
||||||
|
.and_then(|r| r.try_get::<bool>("", "ok").ok())
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !target_ok {
|
||||||
|
return Err(WorkflowError::Validation(
|
||||||
|
"委派目标用户不存在或不属于当前租户".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let mut active: task::ActiveModel = task_model.into();
|
let mut active: task::ActiveModel = task_model.into();
|
||||||
active.assignee_id = Set(Some(req.delegate_to));
|
active.assignee_id = Set(Some(req.delegate_to));
|
||||||
active.updated_at = Set(Utc::now());
|
active.updated_at = Set(Utc::now());
|
||||||
|
|||||||
Reference in New Issue
Block a user