gitdataai/lib/service/pull_request/assignee.rs

111 lines
3.6 KiB
Rust

use db::sqlx;
use model::users::UserModel;
use serde::Deserialize;
use session::Session;
use crate::{
AppService, error::AppError, issues::types::IssueAuthor, session_user,
};
#[derive(Debug, Clone, Deserialize, utoipa::ToSchema)]
pub struct AssignPrUser {
pub username: String,
}
impl AppService {
pub async fn pr_assign(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
number: i64,
params: AssignPrUser,
) -> Result<Vec<IssueAuthor>, AppError> {
let user_uid = session_user(ctx)?;
let (repo_id, _) =
self.pr_resolve_repo(ctx, wk_name, repo_name).await?;
let pr = self.pr_resolve(repo_id, number).await?;
let assignee = sqlx::query_as::<_, UserModel>(
"SELECT id, username, display_name, avatar_url, website_url, allow_use, can_search, \
last_sign_in_at, created_at, updated_at \
FROM \"user\" WHERE username = $1 AND allow_use = true",
)
.bind(&params.username)
.fetch_optional(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?
.ok_or(AppError::UserNotFound)?;
sqlx::query(
"INSERT INTO pull_request_assignee (pull_request, \"user\", assigned_by, created_at) \
VALUES ($1, $2, $3, $4) ON CONFLICT (pull_request, \"user\") DO NOTHING",
)
.bind(pr.id)
.bind(assignee.id)
.bind(user_uid)
.bind(chrono::Utc::now())
.execute(self.db.writer())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
self.pr_assignees_list(pr.id).await
}
pub async fn pr_unassign(
&self,
ctx: &Session,
wk_name: &str,
repo_name: &str,
number: i64,
username: &str,
) -> Result<Vec<IssueAuthor>, AppError> {
let _user_uid = session_user(ctx)?;
let (repo_id, _) =
self.pr_resolve_repo(ctx, wk_name, repo_name).await?;
let pr = self.pr_resolve(repo_id, number).await?;
let assignee = sqlx::query_as::<_, UserModel>(
"SELECT id, username, display_name, avatar_url, website_url, allow_use, can_search, \
last_sign_in_at, created_at, updated_at \
FROM \"user\" WHERE username = $1",
)
.bind(username)
.fetch_optional(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?
.ok_or(AppError::UserNotFound)?;
sqlx::query("DELETE FROM pull_request_assignee WHERE pull_request = $1 AND \"user\" = $2")
.bind(pr.id)
.bind(assignee.id)
.execute(self.db.writer())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
self.pr_assignees_list(pr.id).await
}
pub async fn pr_assignees_list(
&self,
pr_id: uuid::Uuid,
) -> Result<Vec<IssueAuthor>, AppError> {
let assignees = sqlx::query_as::<_, UserModel>(
"SELECT u.id, u.username, u.display_name, u.avatar_url, u.website_url, u.allow_use, u.can_search, \
u.last_sign_in_at, u.created_at, u.updated_at \
FROM pull_request_assignee pa INNER JOIN \"user\" u ON u.id = pa.\"user\" \
WHERE pa.pull_request = $1 \
ORDER BY u.username ASC",
)
.bind(pr_id)
.fetch_all(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(assignees
.into_iter()
.map(|u| crate::issues::types::issue_author(u))
.collect())
}
}