194c44c
use git::share::access::authorize_repo_access;
use git::share::errors::GitError;
use models::repo::repos;
use models::space::spaces;
use jwt::Session;
use jwt::SessionUser;
use uuid::Uuid;
use crate::errors::CiApiError;
use crate::service::CiService;
type AccessResult<T> = Result<T, CiApiError>;
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<Option<i64>> {
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<i64> {
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<Option<i64>> {
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: i64) -> AccessResult<bool> {
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())
}