use std::future::Future; use std::pin::Pin; use actix_web::dev::Payload; use actix_web::{FromRequest, HttpRequest}; use jwt::Session; use serde::Deserialize; use utoipa::IntoParams; use crate::errors::ApiError; use crate::service::GitService; use crate::share::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 FromRequest for RepoPath { type Error = ApiError; type Future = Pin>>>; fn from_request(request: &HttpRequest, _payload: &mut Payload) -> Self::Future { let request = request.clone(); Box::pin(async move { actix_web::web::Path::::from_request(&request, &mut Payload::None) .await .map(|value| value.into_inner()) .map_err(|_| ApiError::bad_request()) }) } } pub fn ensure_caller(session: &Session) -> Result { 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), 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())?; access::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, ApiError> { if ctx.model.is_private { let uid = session.uid().ok_or(ApiError::unauthorized())?; access::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, i64), 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())?; access::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, i64), 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())?; access::authorize_repo_access(service, uid, &ctx, true, true) .await .map_err(super::super::errors::GitApiError::from)?; Ok((ctx, uid)) }