d3d11f4
use axum::extract::{FromRequestParts, Path};
use axum::http::request::Parts;
use serde::Deserialize;
use session_layer::{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))
}
pub async fn require_repo_admin(
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, true)
.await
.map_err(super::super::errors::GitApiError::from)?;
Ok((ctx, uid))
}