use git::share::access::authorize_repo_access; use git::share::errors::GitError; use models::repo::repos; use models::space::spaces; use session::Session; use session::SessionUser; use uuid::Uuid; use crate::errors::CiApiError; use crate::service::CiService; type AccessResult = Result; fn map_git_error(error: GitError) -> CiApiError { match error { GitError::NotFound => CiApiError::NotFound, GitError::Unauthorized => CiApiError::Unauthorized, GitError::Forbidden => CiApiError::Forbidden, other => CiApiError::Internal(other.to_string()), } } impl CiService { pub async fn require_read( &self, session: &Session, repo: &repos::Model, ) -> AccessResult> { match session.uid() { Some(uid) => { let ctx = self .git_context(repo) .await .map_err(|e| CiApiError::Internal(e.to_string()))?; authorize_repo_access( &git::service::GitService::new(self.state.clone()), uid, &ctx, false, false, ) .await .map_err(map_git_error)?; Ok(Some(uid)) } None if !repo.is_private => Ok(None), None => Err(CiApiError::Unauthorized), } } pub async fn require_write( &self, session: &Session, repo: &repos::Model, ) -> AccessResult { let uid = session.uid().ok_or(CiApiError::Unauthorized)?; let ctx = self .git_context(repo) .await .map_err(|e| CiApiError::Internal(e.to_string()))?; authorize_repo_access( &git::service::GitService::new(self.state.clone()), uid, &ctx, true, false, ) .await .map_err(map_git_error)?; Ok(uid) } pub async fn require_space_read( &self, session: &Session, space: &spaces::Model, ) -> AccessResult> { match session.uid() { Some(uid) => { if space.owner_id != uid && !is_member(self, space.id, uid).await? { return Err(CiApiError::Forbidden); } Ok(Some(uid)) } None if !space.is_private => Ok(None), None => Err(CiApiError::Unauthorized), } } } async fn is_member(service: &CiService, space_id: Uuid, uid: Uuid) -> AccessResult { use models::space::space_members; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; let row = space_members::Entity::find() .filter(space_members::Column::SpaceId.eq(space_id)) .filter(space_members::Column::UserId.eq(uid)) .filter(space_members::Column::LeftAt.is_null()) .one(service.db_read()) .await .map_err(|error| CiApiError::Internal(format!("membership lookup failed: {error}")))?; Ok(row.is_some()) }