Skip to content
Clone
main
117 lines 3.3 KB Rust
use git::facade as access;
use git::facade::GitContext;
use models::pull_request::pull_requests;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
use uuid::Uuid;
use crate::errors::PullError;
use crate::services::service::PullService;
#[derive(Clone)]
pub struct PullHandle {
pub ctx: GitContext,
pub pull: pull_requests::Model,
pub caller: Option<i64>,
pub admin: bool,
}
pub async fn repo_read(
svc: &PullService,
viewer: Option<i64>,
space_name: String,
repo_name: String,
) -> Result<(GitContext, Option<i64>), PullError> {
let ctx = svc.git.context(space_name, repo_name).await?;
if ctx.model.is_private {
let uid = viewer.ok_or(PullError::Unauthorized)?;
access::authorize_repo_access(&svc.git, uid, &ctx, false, false).await?;
return Ok((ctx, Some(uid)));
}
Ok((ctx, viewer))
}
pub async fn repo_write(
svc: &PullService,
uid: i64,
space_name: String,
repo_name: String,
) -> Result<(GitContext, i64), PullError> {
let ctx = svc.git.context(space_name, repo_name).await?;
access::authorize_repo_access(&svc.git, uid, &ctx, true, false).await?;
Ok((ctx, uid))
}
pub async fn is_admin(svc: &PullService, uid: i64, ctx: &GitContext) -> bool {
access::authorize_repo_access(&svc.git, uid, ctx, true, true)
.await
.is_ok()
}
/// 按 PR 编号(`123`)或 UUID 在仓库内定位合并请求。
pub async fn find_pull(
svc: &PullService,
repo_id: Uuid,
pull_ref: &str,
) -> Result<pull_requests::Model, PullError> {
let trimmed = pull_ref.trim();
if trimmed.is_empty() {
return Err(PullError::BadRequest("empty pull reference".to_string()));
}
let row = if let Ok(number) = trimmed.parse::<i32>() {
pull_requests::Entity::find()
.filter(pull_requests::Column::RepoId.eq(repo_id))
.filter(pull_requests::Column::AutoincrementId.eq(number))
.one(svc.db_read())
.await?
} else if let Ok(id) = Uuid::parse_str(trimmed) {
pull_requests::Entity::find()
.filter(pull_requests::Column::RepoId.eq(repo_id))
.filter(pull_requests::Column::Id.eq(id))
.one(svc.db_read())
.await?
} else {
return Err(PullError::BadRequest(
"pull reference must be a number or a uuid".to_string(),
));
};
row.ok_or(PullError::NotFound)
}
pub async fn pull_handle_read(
svc: &PullService,
viewer: Option<i64>,
space_name: String,
repo_name: String,
pull_ref: String,
) -> Result<PullHandle, PullError> {
let (ctx, caller) = repo_read(svc, viewer, space_name, repo_name).await?;
let pull = find_pull(svc, ctx.model.id, &pull_ref).await?;
let admin = match caller {
Some(uid) => is_admin(svc, uid, &ctx).await,
None => false,
};
Ok(PullHandle {
ctx,
pull,
caller,
admin,
})
}
pub async fn pull_handle_write(
svc: &PullService,
uid: i64,
space_name: String,
repo_name: String,
pull_ref: String,
) -> Result<PullHandle, PullError> {
let (ctx, uid) = repo_write(svc, uid, space_name, repo_name).await?;
let pull = find_pull(svc, ctx.model.id, &pull_ref).await?;
let admin = is_admin(svc, uid, &ctx).await;
Ok(PullHandle {
ctx,
pull,
caller: Some(uid),
admin,
})
}