gitdataai/lib/channel/http/handler/category.rs

147 lines
4.9 KiB
Rust

use chrono::Utc;
use uuid::Uuid;
use crate::event::{UserInfo, WorkspaceInfo, category};
use crate::{ChannelBus, ChannelError, ChannelResult};
use super::MAX_CATEGORY_NAME_LEN;
use super::WsHandler;
use super::WsOutEvent;
impl WsHandler {
pub(super) async fn category_create(
bus: &ChannelBus,
user_id: Uuid,
workspace: Uuid,
name: String,
position: Option<i32>,
) -> ChannelResult<Option<WsOutEvent>> {
if name.is_empty() || name.len() > MAX_CATEGORY_NAME_LEN {
return Err(ChannelError::Validation(
"invalid category name".into(),
));
}
Self::ensure_workspace_member(bus, user_id, workspace).await?;
let row = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
"INSERT INTO room_category (wk, name, position, created_at, updated_at) \
VALUES ($1, $2, $3, now(), now()) \
RETURNING id, wk, name, position, collapsed, created_at, updated_at",
)
.bind(workspace)
.bind(&name)
.bind(position.unwrap_or(0))
.fetch_one(bus.inner.db.writer())
.await?;
let cc_workspace = bus
.lookup_workspace(workspace)
.await
.unwrap_or_else(|_| WorkspaceInfo::unknown(workspace));
let cc_user = bus
.lookup_user(user_id)
.await
.unwrap_or_else(|_| UserInfo::unknown(user_id));
let data = category::CategoryCreatedService {
id: row.id,
project: cc_workspace,
name: row.name,
position: row.position,
created_by: cc_user,
created_at: row.created_at,
};
bus.workspace_changed(workspace).await?;
Ok(Some(WsOutEvent::CategoryCreated {
workspace: data.project.clone(),
data,
}))
}
pub(super) async fn category_update(
bus: &ChannelBus,
user_id: Uuid,
id: Uuid,
name: Option<String>,
position: Option<i32>,
) -> ChannelResult<Option<WsOutEvent>> {
let old = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
"SELECT id, wk, name, position, collapsed, created_at, updated_at \
FROM room_category WHERE id = $1",
)
.bind(id)
.fetch_one(bus.inner.db.reader())
.await?;
Self::ensure_workspace_member(bus, user_id, old.wk).await?;
let new_name = name.unwrap_or(old.name.clone());
let new_position = position.unwrap_or(old.position);
db::sqlx::query(
"UPDATE room_category SET name = $2, position = $3, updated_at = now() WHERE id = $1",
)
.bind(id)
.bind(&new_name)
.bind(new_position)
.execute(bus.inner.db.writer())
.await?;
let cu_workspace = bus
.lookup_workspace(old.wk)
.await
.unwrap_or_else(|_| WorkspaceInfo::unknown(old.wk));
let cu_user = bus
.lookup_user(user_id)
.await
.unwrap_or_else(|_| UserInfo::unknown(user_id));
let data = category::CategoryUpdatedService {
id,
project: cu_workspace,
name: Some(new_name),
position: Some(new_position),
updated_by: cu_user,
updated_at: Utc::now(),
};
bus.workspace_changed(old.wk).await?;
Ok(Some(WsOutEvent::CategoryUpdated {
workspace: data.project.clone(),
data,
}))
}
pub(super) async fn category_delete(
bus: &ChannelBus,
_user_id: Uuid,
id: Uuid,
) -> ChannelResult<Option<WsOutEvent>> {
let existing = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
"SELECT id, wk, name, position, collapsed, created_at, updated_at \
FROM room_category WHERE id = $1",
)
.bind(id)
.fetch_one(bus.inner.db.reader())
.await?;
Self::ensure_workspace_member(bus, _user_id, existing.wk).await?;
let row = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
"DELETE FROM room_category WHERE id = $1 \
RETURNING id, wk, name, position, collapsed, created_at, updated_at",
)
.bind(id)
.fetch_one(bus.inner.db.writer())
.await?;
let cd_workspace = bus
.lookup_workspace(row.wk)
.await
.unwrap_or_else(|_| WorkspaceInfo::unknown(row.wk));
let cd_user = bus
.lookup_user(_user_id)
.await
.unwrap_or_else(|_| UserInfo::unknown(_user_id));
let data = category::CategoryDeletedService {
id: row.id,
project: cd_workspace.clone(),
deleted_by: cd_user,
deleted_at: Utc::now(),
};
bus.workspace_changed(row.wk).await?;
Ok(Some(WsOutEvent::CategoryDeleted {
workspace: cd_workspace,
data,
}))
}
}