Skip to content
Clone
030e59e
63 lines 2.2 KB Rust
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 crate::metrics;
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<CommentView> {
let _timer = metrics::Timer::start(metrics::FEATURE_COMMENTS_CREATE);
let result: IssueResult<CommentView> = async {
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::now_v7();
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))
}
.await;
metrics::record_outcome(metrics::FEATURE_COMMENTS_CREATE, &result);
result
}