2ae9196
ZhenYi
feat(lib/git): add HTTP handler tree with routes and errors across analysis, archives, blobs, branches, commits, conflicts, content, diffs, hooks, lfs, logs, maintenance, packs, patches, pipelines, refs, remotes, repos, signatures, submodules, tags, trees
2ae9196
use axum::extract::{FromRequestParts, Path};
use axum::http::request::Parts;
use serde::Deserialize;
use session::{Session, SessionUser};
use utoipa::IntoParams;
use uuid::Uuid;
use crate::errors::ApiError;
use crate::service::GitService;
use crate::share::access::authorize_repo_access;
#[derive(Debug, Clone, Deserialize, IntoParams)]
pub struct RepoPath {
pub space_name: String,
pub repo_name: String,
}
#[derive(Debug, Clone, Deserialize, IntoParams)]
pub struct RepoPathRev {
pub space_name: String,
pub repo_name: String,
pub revision: String,
}
impl<S> FromRequestParts<S> for RepoPath
where
S: Send + Sync,
{
type Rejection = ApiError;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
Path::<RepoPath>::from_request_parts(parts, state)
.await
.map(|Path(p)| p)
.map_err(|_| ApiError::bad_request())
}
}
pub fn ensure_caller(session: &Session) -> Result<Uuid, ApiError> {
session.uid().ok_or(ApiError::unauthorized())
}
pub async fn resolve_reader(
service: &GitService,
session: &Session,
space_name: String,
repo_name: String,
) -> Result<(crate::context::facade::GitContext, Option<Uuid>), ApiError> {
let ctx = service
.context(space_name, repo_name)
.await
.map_err(super::super::errors::GitApiError::from)?;
if ctx.model.is_private {
let uid = session.uid().ok_or(ApiError::unauthorized())?;
authorize_repo_access(service, uid, &ctx, false, false)
.await
.map_err(super::super::errors::GitApiError::from)?;
Ok((ctx, Some(uid)))
} else {
Ok((ctx, session.uid()))
}
}
pub async fn ensure_read_access(
service: &GitService,
session: &Session,
ctx: &crate::context::facade::GitContext,
) -> Result<Option<Uuid>, ApiError> {
if ctx.model.is_private {
let uid = session.uid().ok_or(ApiError::unauthorized())?;
authorize_repo_access(service, uid, ctx, false, false)
.await
.map_err(super::super::errors::GitApiError::from)?;
Ok(Some(uid))
} else {
Ok(session.uid())
}
}
pub async fn require_writer(
service: &GitService,
session: &Session,
space_name: String,
repo_name: String,
) -> Result<(crate::context::facade::GitContext, Uuid), ApiError> {
let ctx = service
.context(space_name, repo_name)
.await
.map_err(super::super::errors::GitApiError::from)?;
let uid = session.uid().ok_or(ApiError::unauthorized())?;
authorize_repo_access(service, uid, &ctx, true, false)
.await
.map_err(super::super::errors::GitApiError::from)?;
Ok((ctx, uid))
}