fix(handlers): add handlers
This commit is contained in:
79
src/services/authorization.rs
Normal file
79
src/services/authorization.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use common_telemetry::AppError;
|
||||
use sqlx::PgPool;
|
||||
use tracing::instrument;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AuthorizationService {
|
||||
pool: PgPool,
|
||||
}
|
||||
|
||||
impl AuthorizationService {
|
||||
/// 创建权限服务实例。
|
||||
pub fn new(pool: PgPool) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
/// 获取用户在指定租户下的权限编码集合(去重)。
|
||||
///
|
||||
/// 说明:
|
||||
/// - 权限来源于用户所属角色(user_roles → roles)及角色绑定权限(role_permissions → permissions)。
|
||||
///
|
||||
/// 输入:
|
||||
/// - `tenant_id`:租户 ID
|
||||
/// - `user_id`:用户 ID
|
||||
///
|
||||
/// 输出:
|
||||
/// - 权限编码数组(如 `tenant:read` / `user:write`)
|
||||
///
|
||||
/// 异常:
|
||||
/// - 数据库查询失败
|
||||
pub async fn list_permissions_for_user(
|
||||
&self,
|
||||
tenant_id: Uuid,
|
||||
user_id: Uuid,
|
||||
) -> Result<Vec<String>, AppError> {
|
||||
let query = r#"
|
||||
SELECT DISTINCT p.code
|
||||
FROM permissions p
|
||||
JOIN role_permissions rp ON rp.permission_id = p.id
|
||||
JOIN user_roles ur ON ur.role_id = rp.role_id
|
||||
JOIN roles r ON r.id = ur.role_id
|
||||
WHERE r.tenant_id = $1 AND ur.user_id = $2
|
||||
"#;
|
||||
let rows = sqlx::query_scalar::<_, String>(query)
|
||||
.bind(tenant_id)
|
||||
.bind(user_id)
|
||||
.fetch_all(&self.pool)
|
||||
.await?;
|
||||
Ok(rows)
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
/// 校验用户是否具备指定权限,不满足则直接返回权限拒绝错误。
|
||||
///
|
||||
/// 业务规则:
|
||||
/// - 若用户权限集合中不包含 `permission_code`,返回 `PermissionDenied(permission_code)`。
|
||||
///
|
||||
/// 输入:
|
||||
/// - `tenant_id`:租户 ID
|
||||
/// - `user_id`:用户 ID
|
||||
/// - `permission_code`:权限编码
|
||||
///
|
||||
/// 输出:
|
||||
/// - 成功返回 `()`;失败返回权限拒绝错误
|
||||
pub async fn require_permission(
|
||||
&self,
|
||||
tenant_id: Uuid,
|
||||
user_id: Uuid,
|
||||
permission_code: &str,
|
||||
) -> Result<(), AppError> {
|
||||
let permissions = self.list_permissions_for_user(tenant_id, user_id).await?;
|
||||
if permissions.iter().any(|p| p == permission_code) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(AppError::PermissionDenied(permission_code.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user