JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Add access list to private repos

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨8c17f89

Showing ⁨⁨2⁩ changed files⁩ with ⁨⁨70⁩ insertions⁩ and ⁨⁨7⁩ deletions⁩

giterated-daemon/src/backend/git.rs

View file
@@ -5,7 +5,7 @@ use git2::BranchType;
5 5 use giterated_models::instance::{Instance, RepositoryCreateRequest};
6 6
7 7 use giterated_models::repository::{
8 Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository,
8 AccessList, Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository,
9 9 RepositoryCommitBeforeRequest, RepositoryDiff, RepositoryDiffFile, RepositoryDiffFileChunk,
10 10 RepositoryDiffFileInfo, RepositoryDiffFileStatus, RepositoryDiffPatchRequest,
11 11 RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest,
@@ -44,10 +44,57 @@ pub struct GitRepository {
44 44 impl GitRepository {
45 45 // Separate function because "Private" will be expanded later
46 46 /// Checks if the user is allowed to view this repository
47 pub fn can_user_view_repository(&self, user: Option<&User>) -> bool {
48 !matches!(self.visibility, RepositoryVisibility::Private)
49 || (matches!(self.visibility, RepositoryVisibility::Private)
50 && Some(&self.owner_user) == user)
47 pub async fn can_user_view_repository(
48 &self,
49 our_instance: &Instance,
50 user: Option<&User>,
51 settings: &Arc<Mutex<dyn MetadataBackend + Send>>,
52 ) -> bool {
53 if matches!(self.visibility, RepositoryVisibility::Public) {
54 return true;
55 }
56
57 // User must exist for any further checks to pass
58 let user = match user {
59 Some(user) => user,
60 None => return false,
61 };
62
63 if *user == self.owner_user {
64 // owner can always view
65 return true;
66 }
67
68 if matches!(self.visibility, RepositoryVisibility::Private) {
69 // Check if the user can view
70 let mut settings = settings.lock().await;
71
72 let access_list = settings
73 .repository_get(
74 &Repository {
75 owner: self.owner_user.clone(),
76 name: self.name.clone(),
77 instance: our_instance.clone(),
78 },
79 AccessList::name(),
80 )
81 .await;
82
83 let access_list: AccessList = match access_list {
84 Ok(list) => serde_json::from_value(list.0).unwrap(),
85 Err(_) => {
86 return false;
87 }
88 };
89
90 access_list
91 .0
92 .iter()
93 .find(|access_list_user| *access_list_user == user)
94 .is_some()
95 } else {
96 false
97 }
51 98 }
52 99
53 100 // 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 {
199 246 };
200 247
201 248 if let Some(requester) = requester {
202 if !repository.can_user_view_repository(Some(requester)) {
249 if !repository
250 .can_user_view_repository(&self.instance, Some(requester), &self.settings_provider)
251 .await
252 {
203 253 return Err(GitBackendError::RepositoryNotFound {
204 254 owner_user: repository.owner_user.to_string(),
205 255 name: repository.name.clone(),

giterated-models/src/repository/settings.rs

View file
@@ -1,4 +1,6 @@
1 use crate::settings::Setting;
1 use serde::{Deserialize, Serialize};
2
3 use crate::{settings::Setting, user::User};
2 4
3 5 use super::{DefaultBranch, RepositoryVisibility};
4 6
@@ -7,3 +9,14 @@ impl Setting for DefaultBranch {
7 9 "default_branch"
8 10 }
9 11 }
12
13 #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
14 #[repr(transparent)]
15 #[serde(transparent)]
16 pub struct AccessList(pub Vec<User>);
17
18 impl Setting for AccessList {
19 fn name() -> &'static str {
20 "access_list"
21 }
22 }