diff --git a/giterated-daemon/src/backend/git.rs b/giterated-daemon/src/backend/git.rs index 7ad1a83..2f3a945 100644 --- a/giterated-daemon/src/backend/git.rs +++ b/giterated-daemon/src/backend/git.rs @@ -5,7 +5,7 @@ use git2::BranchType; use giterated_models::instance::{Instance, RepositoryCreateRequest}; use giterated_models::repository::{ - Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository, + AccessList, Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository, RepositoryCommitBeforeRequest, RepositoryDiff, RepositoryDiffFile, RepositoryDiffFileChunk, RepositoryDiffFileInfo, RepositoryDiffFileStatus, RepositoryDiffPatchRequest, RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest, @@ -44,10 +44,57 @@ pub struct GitRepository { impl GitRepository { // Separate function because "Private" will be expanded later /// Checks if the user is allowed to view this repository - pub fn can_user_view_repository(&self, user: Option<&User>) -> bool { - !matches!(self.visibility, RepositoryVisibility::Private) - || (matches!(self.visibility, RepositoryVisibility::Private) - && Some(&self.owner_user) == user) + pub async fn can_user_view_repository( + &self, + our_instance: &Instance, + user: Option<&User>, + settings: &Arc>, + ) -> bool { + if matches!(self.visibility, RepositoryVisibility::Public) { + return true; + } + + // User must exist for any further checks to pass + let user = match user { + Some(user) => user, + None => return false, + }; + + if *user == self.owner_user { + // owner can always view + return true; + } + + if matches!(self.visibility, RepositoryVisibility::Private) { + // Check if the user can view + let mut settings = settings.lock().await; + + let access_list = settings + .repository_get( + &Repository { + owner: self.owner_user.clone(), + name: self.name.clone(), + instance: our_instance.clone(), + }, + AccessList::name(), + ) + .await; + + let access_list: AccessList = match access_list { + Ok(list) => serde_json::from_value(list.0).unwrap(), + Err(_) => { + return false; + } + }; + + access_list + .0 + .iter() + .find(|access_list_user| *access_list_user == user) + .is_some() + } else { + false + } } // This is in it's own function because I assume I'll have to add logic to this later @@ -199,7 +246,10 @@ impl GitBackend { }; if let Some(requester) = requester { - if !repository.can_user_view_repository(Some(requester)) { + if !repository + .can_user_view_repository(&self.instance, Some(requester), &self.settings_provider) + .await + { return Err(GitBackendError::RepositoryNotFound { owner_user: repository.owner_user.to_string(), name: repository.name.clone(), diff --git a/giterated-models/src/repository/settings.rs b/giterated-models/src/repository/settings.rs index f23fe3c..fd3926a 100644 --- a/giterated-models/src/repository/settings.rs +++ b/giterated-models/src/repository/settings.rs @@ -1,4 +1,6 @@ -use crate::settings::Setting; +use serde::{Deserialize, Serialize}; + +use crate::{settings::Setting, user::User}; use super::{DefaultBranch, RepositoryVisibility}; @@ -7,3 +9,14 @@ impl Setting for DefaultBranch { "default_branch" } } + +#[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[repr(transparent)] +#[serde(transparent)] +pub struct AccessList(pub Vec); + +impl Setting for AccessList { + fn name() -> &'static str { + "access_list" + } +}