164 lines
5.4 KiB
Rust
164 lines
5.4 KiB
Rust
use crate::AppService;
|
|
use crate::errors::AppError;
|
|
use session::Session;
|
|
use models::active_enums::MemberRole;
|
|
use models::project::{project_members, projects};
|
|
use models::repos::repo;
|
|
use sea_orm::*;
|
|
use uuid::Uuid;
|
|
|
|
pub enum RepoPermission {
|
|
Read,
|
|
Write,
|
|
}
|
|
|
|
impl AppService {
|
|
pub async fn check_repo_permission(
|
|
&self,
|
|
ctx: &Session,
|
|
namespace: &str,
|
|
repo_name: &str,
|
|
required_permission: RepoPermission,
|
|
) -> Result<(repo::Model, projects::Model), AppError> {
|
|
let repository = repo::Entity::find()
|
|
.filter(repo::Column::Namespace.eq(namespace))
|
|
.filter(repo::Column::RepoName.eq(repo_name))
|
|
.one(&self.db)
|
|
.await?
|
|
.ok_or(AppError::NotFound("Repository not found".to_string()))?;
|
|
|
|
let project = projects::Entity::find()
|
|
.filter(projects::Column::Name.eq(namespace))
|
|
.one(&self.db)
|
|
.await?
|
|
.ok_or(AppError::ProjectNotFound)?;
|
|
|
|
if repository.project_uid != Some(project.uid) {
|
|
return Err(AppError::NotFound(
|
|
"Repository not found in project".to_string(),
|
|
));
|
|
}
|
|
|
|
let user_uid = ctx.user();
|
|
|
|
match required_permission {
|
|
RepoPermission::Read => {
|
|
if project.is_public && !repository.is_private {
|
|
return Ok((repository, project));
|
|
}
|
|
|
|
let user_uid = user_uid.ok_or(AppError::Unauthorized)?;
|
|
|
|
let member = project_members::Entity::find()
|
|
.filter(project_members::Column::ProjectId.eq(project.uid))
|
|
.filter(project_members::Column::UserId.eq(user_uid))
|
|
.one(&self.db)
|
|
.await?;
|
|
|
|
if member.is_some() {
|
|
Ok((repository, project))
|
|
} else {
|
|
Err(AppError::PermissionDenied)
|
|
}
|
|
}
|
|
RepoPermission::Write => {
|
|
let user_uid = user_uid.ok_or(AppError::Unauthorized)?;
|
|
|
|
let member = project_members::Entity::find()
|
|
.filter(project_members::Column::ProjectId.eq(project.uid))
|
|
.filter(project_members::Column::UserId.eq(user_uid))
|
|
.one(&self.db)
|
|
.await?
|
|
.ok_or(AppError::PermissionDenied)?;
|
|
|
|
if member.scope == MemberRole::Owner || member.scope == MemberRole::Admin {
|
|
Ok((repository, project))
|
|
} else {
|
|
Err(AppError::PermissionDenied)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn check_repo_read_permission(
|
|
&self,
|
|
ctx: &Session,
|
|
namespace: &str,
|
|
repo_name: &str,
|
|
) -> Result<(repo::Model, projects::Model), AppError> {
|
|
self.check_repo_permission(ctx, namespace, repo_name, RepoPermission::Read)
|
|
.await
|
|
}
|
|
|
|
pub async fn check_repo_write_permission(
|
|
&self,
|
|
ctx: &Session,
|
|
namespace: &str,
|
|
repo_name: &str,
|
|
) -> Result<(repo::Model, projects::Model), AppError> {
|
|
self.check_repo_permission(ctx, namespace, repo_name, RepoPermission::Write)
|
|
.await
|
|
}
|
|
|
|
pub async fn check_repo_permission_by_uid(
|
|
&self,
|
|
ctx: &Session,
|
|
repo_uid: Uuid,
|
|
required_permission: RepoPermission,
|
|
) -> Result<(repo::Model, projects::Model), AppError> {
|
|
let repository = repo::Entity::find_by_id(repo_uid)
|
|
.one(&self.db)
|
|
.await?
|
|
.ok_or(AppError::NotFound("Repository not found".to_string()))?;
|
|
|
|
let project_uid = repository.project_uid.ok_or(AppError::NotFound(
|
|
"Repository has no associated project".to_string(),
|
|
))?;
|
|
|
|
let project = projects::Entity::find_by_id(project_uid)
|
|
.one(&self.db)
|
|
.await?
|
|
.ok_or(AppError::ProjectNotFound)?;
|
|
|
|
let user_uid = ctx.user();
|
|
|
|
match required_permission {
|
|
RepoPermission::Read => {
|
|
if project.is_public && !repository.is_private {
|
|
return Ok((repository, project));
|
|
}
|
|
|
|
let user_uid = user_uid.ok_or(AppError::Unauthorized)?;
|
|
|
|
let member = project_members::Entity::find()
|
|
.filter(project_members::Column::ProjectId.eq(project.uid))
|
|
.filter(project_members::Column::UserId.eq(user_uid))
|
|
.one(&self.db)
|
|
.await?;
|
|
|
|
if member.is_some() {
|
|
Ok((repository, project))
|
|
} else {
|
|
Err(AppError::PermissionDenied)
|
|
}
|
|
}
|
|
RepoPermission::Write => {
|
|
let user_uid = user_uid.ok_or(AppError::Unauthorized)?;
|
|
|
|
let member = project_members::Entity::find()
|
|
.filter(project_members::Column::ProjectId.eq(project.uid))
|
|
.filter(project_members::Column::UserId.eq(user_uid))
|
|
.one(&self.db)
|
|
.await?
|
|
.ok_or(AppError::PermissionDenied)?;
|
|
|
|
if member.scope == MemberRole::Owner || member.scope == MemberRole::Admin {
|
|
Ok((repository, project))
|
|
} else {
|
|
Err(AppError::PermissionDenied)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|