111 lines
3.6 KiB
Rust
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(¶ms.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())
|
|
}
|
|
}
|