use db::conn::sea_orm::*; use db::issue::comment as comment_entity; use time::OffsetDateTime; use uuid::Uuid; use crate::error::{IssueError, IssueResult}; use crate::features::IssueService; use super::super::super::issue::usecase::load_issue; use super::super::{CommentView, CreateCommentOption}; use super::helpers::require_authenticated; pub async fn create_comment( svc: &IssueService, actor: Uuid, channel_id: Uuid, issue_id: Uuid, input: CreateCommentOption, ) -> IssueResult { require_authenticated(actor)?; if input.content.trim().is_empty() || input.content.len() > svc.config.max_comment_len { return Err(IssueError::BadRequest(format!( "comment length must be in 1..={}", svc.config.max_comment_len ))); } let _issue = load_issue(svc, channel_id, issue_id).await?; if let Some(parent_id) = input.parent_id { let db = svc.db.reader(); let parent = comment_entity::Entity::find_by_id(parent_id) .one(&db) .await? .ok_or_else(|| IssueError::NotFound(format!("comment {parent_id}")))?; if parent.issue_id != Some(issue_id) { return Err(IssueError::BadRequest( "parent comment must belong to the same issue".into(), )); } } let db = svc.db.writer(); let now = OffsetDateTime::now_utc(); let id = Uuid::new_v4(); let active: comment_entity::ActiveModel = comment_entity::ActiveModel::builder() .set_id(id) .set_issue_id(issue_id) .set_parent_id(input.parent_id) .set_poster_id(actor) .set_content(input.content) .set_created_at(now) .set_updated_at(None) .into(); let saved = active.insert(&db).await?; Ok(CommentView::from(saved)) }