gitdataai/libs/service/utils/repo.rs
2026-04-15 09:08:09 +08:00

84 lines
2.9 KiB
Rust

use crate::AppService;
use crate::error::AppError;
use models::projects::{MemberRole, project_members};
use models::repos::{repo, repo_history_name};
use sea_orm::*;
use session::Session;
impl AppService {
pub async fn utils_find_repo(
&self,
namespace: String,
repo_name: String,
context: &Session,
) -> Result<repo::Model, AppError> {
let project = self.utils_find_project_by_name(namespace).await?;
// Propagate DB errors — silently treating them as "not found" would mask infrastructure issues.
let repo = repo::Entity::find()
.filter(repo::Column::RepoName.eq(repo_name.clone()))
.filter(repo::Column::Project.eq(project.id))
.one(&self.db)
.await?;
let repo = match repo {
Some(r) => r,
// Fall back to historical repo names (renamed repos).
None => {
let hist = repo_history_name::Entity::find()
.filter(repo_history_name::Column::Name.eq(repo_name))
.filter(repo_history_name::Column::Project.eq(project.id))
.one(&self.db)
.await?
.ok_or(AppError::RepoNotFound)?;
repo::Entity::find()
.filter(repo::Column::Id.eq(hist.repo))
.filter(repo::Column::Project.eq(project.id))
.one(&self.db)
.await?
.ok_or(AppError::RepoNotFound)?
}
};
if repo.is_private {
if let Some(user_uid) = context.user() {
let project_member = project_members::Entity::find()
.filter(project_members::Column::Project.eq(repo.project))
.filter(project_members::Column::User.eq(user_uid))
.one(&self.db)
.await?;
if project_member.is_none() {
return Err(AppError::RepoForBidAccess);
}
} else {
return Err(AppError::RepoForBidAccess);
}
}
Ok(repo)
}
pub async fn utils_check_repo_admin(
&self,
namespace: String,
repo_name: String,
context: &Session,
) -> Result<repo::Model, AppError> {
let user_uid = context.user().ok_or(AppError::Unauthorized)?;
let repo = self.utils_find_repo(namespace, repo_name, context).await?;
let member = project_members::Entity::find()
.filter(project_members::Column::Project.eq(repo.project))
.filter(project_members::Column::User.eq(user_uid))
.one(&self.db)
.await?
.ok_or(AppError::NoPower)?;
let role = member.scope_role().map_err(|_| AppError::RoleParseError)?;
if role == MemberRole::Admin || role == MemberRole::Owner {
Ok(repo)
} else {
Err(AppError::NoPower)
}
}
}