fix: resolve E2E audit findings and add Phase C frontend pages
- Fix audit_log handler multi-tenant bug: use Extension<TenantContext>
instead of hardcoded default_tenant_id
- Fix sendMessage route mismatch: frontend /messages/send → /messages
- Add POST /users/{id}/roles backend route for role assignment
- Add task.completed event payload: started_by + instance_id for
notification delivery
- Add audit log viewer frontend page (AuditLogViewer.tsx)
- Add language management frontend page (LanguageManager.tsx)
- Add api/auditLogs.ts and api/languages.ts modules
This commit is contained in:
@@ -277,6 +277,70 @@ impl UserService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Replace all role assignments for a user within a tenant.
|
||||
pub async fn assign_roles(
|
||||
user_id: Uuid,
|
||||
tenant_id: Uuid,
|
||||
operator_id: Uuid,
|
||||
role_ids: &[Uuid],
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
) -> AuthResult<Vec<RoleResp>> {
|
||||
// 验证用户存在
|
||||
let _user = user::Entity::find_by_id(user_id)
|
||||
.one(db)
|
||||
.await
|
||||
.map_err(|e| AuthError::Validation(e.to_string()))?
|
||||
.filter(|u| u.tenant_id == tenant_id && u.deleted_at.is_none())
|
||||
.ok_or_else(|| AuthError::Validation("用户不存在".to_string()))?;
|
||||
|
||||
// 验证所有角色存在且属于当前租户
|
||||
if !role_ids.is_empty() {
|
||||
let found = role::Entity::find()
|
||||
.filter(role::Column::Id.is_in(role_ids.iter().copied()))
|
||||
.filter(role::Column::TenantId.eq(tenant_id))
|
||||
.all(db)
|
||||
.await
|
||||
.map_err(|e| AuthError::Validation(e.to_string()))?;
|
||||
if found.len() != role_ids.len() {
|
||||
return Err(AuthError::Validation("部分角色不存在或不属于当前租户".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
// 删除旧的角色分配
|
||||
user_role::Entity::delete_many()
|
||||
.filter(user_role::Column::UserId.eq(user_id))
|
||||
.filter(user_role::Column::TenantId.eq(tenant_id))
|
||||
.exec(db)
|
||||
.await
|
||||
.map_err(|e| AuthError::Validation(e.to_string()))?;
|
||||
|
||||
// 创建新的角色分配
|
||||
let now = chrono::Utc::now();
|
||||
for &role_id in role_ids {
|
||||
let assignment = user_role::ActiveModel {
|
||||
user_id: Set(user_id),
|
||||
role_id: Set(role_id),
|
||||
tenant_id: Set(tenant_id),
|
||||
created_at: Set(now),
|
||||
updated_at: Set(now),
|
||||
created_by: Set(operator_id),
|
||||
updated_by: Set(operator_id),
|
||||
deleted_at: Set(None),
|
||||
version: Set(1),
|
||||
};
|
||||
assignment.insert(db).await.map_err(|e| AuthError::Validation(e.to_string()))?;
|
||||
}
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, Some(operator_id), "user.assign_roles", "user")
|
||||
.with_resource_id(user_id),
|
||||
db,
|
||||
)
|
||||
.await;
|
||||
|
||||
Self::fetch_user_role_resps(user_id, tenant_id, db).await
|
||||
}
|
||||
|
||||
/// Fetch RoleResp DTOs for a given user within a tenant.
|
||||
async fn fetch_user_role_resps(
|
||||
user_id: Uuid,
|
||||
|
||||
Reference in New Issue
Block a user