fix(handlers): add handlers
This commit is contained in:
134
src/services/tenant.rs
Normal file
134
src/services/tenant.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user