Skip to content
Clone
d5939db
118 lines 3.2 KB Rust
use db::project::project_links as link_entity;
use db::project::project_links::Column as Lc;
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, QueryOrder, Set};
use time::OffsetDateTime;
use uuid::Uuid;
use crate::error::{ProjectError, ProjectResult};
use crate::features::lifecycle::usecase::log_activity;
use crate::features::ProjectService;
use crate::permission;
use super::types::{AddLinkCmd, LinkKind, LinkPage, LinkView};
pub async fn add_link(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
cmd: AddLinkCmd,
) -> ProjectResult<LinkView> {
crate::features::authz::require(
svc,
actor,
space_id,
project_id,
permission::MANAGE_LINKS,
)
.await?;
if cmd.related_project_id == project_id {
return Err(ProjectError::BadRequest(
"a project cannot link to itself".into(),
));
}
let kind: db::project::project_links::ProjectLinkKind = cmd.kind.try_into()?;
let id = Uuid::new_v4();
let now = OffsetDateTime::now_utc();
let row = link_entity::ActiveModel {
id: Set(id),
project_id: Set(project_id),
related_project_id: Set(cmd.related_project_id),
kind: Set(kind),
created_by: Set(actor),
created_at: Set(now),
}
.insert(&svc.db.writer())
.await?;
log_activity(svc, project_id, actor, "link_added", "link", Some(id), None).await;
let _ = svc.cache.invalidate_project(project_id).await;
Ok(link_view(&row))
}
pub async fn list_links(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
) -> ProjectResult<LinkPage> {
crate::features::authz::require(svc, actor, space_id, project_id, permission::VIEW_PROJECT)
.await?;
let rows = link_entity::Entity::find()
.filter(Lc::ProjectId.eq(project_id))
.order_by_desc(Lc::CreatedAt)
.all(&svc.db.reader())
.await?;
let items = rows.iter().map(link_view).collect::<Vec<_>>();
let total = items.len() as u64;
Ok(LinkPage { total, items })
}
pub async fn remove_link(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
link_id: Uuid,
) -> ProjectResult<()> {
crate::features::authz::require(
svc,
actor,
space_id,
project_id,
permission::MANAGE_LINKS,
)
.await?;
let deleted = link_entity::Entity::delete_many()
.filter(Lc::Id.eq(link_id))
.filter(Lc::ProjectId.eq(project_id))
.exec(&svc.db.writer())
.await?;
if deleted.rows_affected == 0 {
return Err(ProjectError::NotFound(format!(
"link {link_id} in project {project_id}"
)));
}
log_activity(svc, project_id, actor, "link_removed", "link", Some(link_id), None).await;
let _ = svc.cache.invalidate_project(project_id).await;
Ok(())
}
fn link_view(m: &link_entity::Model) -> LinkView {
LinkView {
id: m.id,
project_id: m.project_id,
related_project_id: m.related_project_id,
kind: m.kind.into(),
created_by: m.created_by,
created_at: m.created_at,
}
}
pub fn links_to_kind(_k: LinkKind) -> LinkKind {
_k
}