fix(handlers): add handlers

This commit is contained in:
2026-01-30 16:31:53 +08:00
parent bb82c75834
commit ce12b997f4
38 changed files with 3746 additions and 317 deletions

134
src/services/tenant.rs Normal file
View File

@@ -0,0 +1,134 @@
use crate::models::{
CreateTenantRequest, Tenant, UpdateTenantRequest, UpdateTenantStatusRequest,
};
use common_telemetry::AppError;
use serde_json::Value;
use sqlx::PgPool;
use tracing::instrument;
use uuid::Uuid;
#[derive(Clone)]
pub struct TenantService {
pool: PgPool,
}
impl TenantService {
/// 创建租户服务实例。
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
#[instrument(skip(self, req))]
/// 创建新租户并初始化默认状态与配置。
///
/// 业务规则:
/// - 默认 `status=active`。
/// - `config` 未提供时默认 `{}`。
///
/// 输出:
/// - 返回新建租户记录(含 `id`
///
/// 异常:
/// - 数据库写入失败(如连接异常、约束失败等)
pub async fn create_tenant(&self, req: CreateTenantRequest) -> Result<Tenant, AppError> {
let config = req.config.unwrap_or_else(|| Value::Object(Default::default()));
let query = r#"
INSERT INTO tenants (name, status, config)
VALUES ($1, 'active', $2)
RETURNING id, name, status, config
"#;
let tenant = sqlx::query_as::<_, Tenant>(query)
.bind(req.name)
.bind(config)
.fetch_one(&self.pool)
.await?;
Ok(tenant)
}
#[instrument(skip(self))]
/// 根据租户 ID 查询租户信息。
///
/// 异常:
/// - 若租户不存在,返回 `NotFound("Tenant not found")`。
pub async fn get_tenant(&self, tenant_id: Uuid) -> Result<Tenant, AppError> {
let query = "SELECT id, name, status, config FROM tenants WHERE id = $1";
sqlx::query_as::<_, Tenant>(query)
.bind(tenant_id)
.fetch_optional(&self.pool)
.await?
.ok_or_else(|| AppError::NotFound("Tenant not found".into()))
}
#[instrument(skip(self, req))]
/// 更新租户基础信息(名称 / 配置)。
///
/// 说明:
/// - 仅更新 `UpdateTenantRequest` 中提供的字段,未提供字段保持不变。
///
/// 异常:
/// - 若租户不存在,返回 `NotFound("Tenant not found")`。
pub async fn update_tenant(
&self,
tenant_id: Uuid,
req: UpdateTenantRequest,
) -> Result<Tenant, AppError> {
let query = r#"
UPDATE tenants
SET
name = COALESCE($1, name),
config = COALESCE($2, config),
updated_at = NOW()
WHERE id = $3
RETURNING id, name, status, config
"#;
sqlx::query_as::<_, Tenant>(query)
.bind(req.name)
.bind(req.config)
.bind(tenant_id)
.fetch_optional(&self.pool)
.await?
.ok_or_else(|| AppError::NotFound("Tenant not found".into()))
}
#[instrument(skip(self, req))]
/// 更新租户状态字段(如 active / disabled
///
/// 异常:
/// - 若租户不存在,返回 `NotFound("Tenant not found")`。
pub async fn update_tenant_status(
&self,
tenant_id: Uuid,
req: UpdateTenantStatusRequest,
) -> Result<Tenant, AppError> {
let query = r#"
UPDATE tenants
SET
status = $1,
updated_at = NOW()
WHERE id = $2
RETURNING id, name, status, config
"#;
sqlx::query_as::<_, Tenant>(query)
.bind(req.status)
.bind(tenant_id)
.fetch_optional(&self.pool)
.await?
.ok_or_else(|| AppError::NotFound("Tenant not found".into()))
}
#[instrument(skip(self))]
/// 删除指定租户。
///
/// 异常:
/// - 若租户不存在,返回 `NotFound("Tenant not found")`。
pub async fn delete_tenant(&self, tenant_id: Uuid) -> Result<(), AppError> {
let result = sqlx::query("DELETE FROM tenants WHERE id = $1")
.bind(tenant_id)
.execute(&self.pool)
.await?;
if result.rows_affected() == 0 {
return Err(AppError::NotFound("Tenant not found".into()));
}
Ok(())
}
}