Implement `FromOperationState` for `AuthenticatedUser` and `AuthenticatedInstance`
Use `AuthenticatedUser` on repository requests so we can filter by privacy. Woohoo! Attempt to filter `UserRepositoriesRequest` responses by visibility to the requester.
parent: tbd commit: 75dcac3
Showing 7 changed files with 184 insertions and 52 deletions
giterated-daemon/src/backend/git.rs
@@ -16,8 +16,10 @@ use giterated_models::repository::{ | ||
16 | 16 | use giterated_models::settings::{AnySetting, Setting}; |
17 | 17 | use giterated_models::user::{User, UserParseError}; |
18 | 18 | use giterated_models::value::{AnyValue, GiteratedObjectValue}; |
19 | use giterated_stack::AuthenticatedUser; | |
19 | 20 | use serde_json::Value; |
20 | 21 | use sqlx::PgPool; |
22 | use std::ops::Deref; | |
21 | 23 | use std::{ |
22 | 24 | path::{Path, PathBuf}, |
23 | 25 | sync::Arc, |
@@ -47,7 +49,7 @@ impl GitRepository { | ||
47 | 49 | pub async fn can_user_view_repository( |
48 | 50 | &self, |
49 | 51 | our_instance: &Instance, |
50 | user: Option<&User>, | |
52 | user: &Option<AuthenticatedUser>, | |
51 | 53 | settings: &Arc<Mutex<dyn MetadataBackend + Send>>, |
52 | 54 | ) -> bool { |
53 | 55 | info!( |
@@ -64,7 +66,7 @@ impl GitRepository { | ||
64 | 66 | None => return false, |
65 | 67 | }; |
66 | 68 | |
67 | if *user == self.owner_user { | |
69 | if *user.deref() == self.owner_user { | |
68 | 70 | // owner can always view |
69 | 71 | return true; |
70 | 72 | } |
@@ -99,7 +101,7 @@ impl GitRepository { | ||
99 | 101 | access_list |
100 | 102 | .0 |
101 | 103 | .iter() |
102 | .find(|access_list_user| *access_list_user == user) | |
104 | .find(|access_list_user| *access_list_user == user.deref()) | |
103 | 105 | .is_some() |
104 | 106 | } else { |
105 | 107 | false |
@@ -241,7 +243,7 @@ impl GitBackend { | ||
241 | 243 | &self, |
242 | 244 | owner: &User, |
243 | 245 | name: &str, |
244 | requester: Option<&User>, | |
246 | requester: &Option<AuthenticatedUser>, | |
245 | 247 | ) -> Result<git2::Repository, GitBackendError> { |
246 | 248 | info!( |
247 | 249 | "Checking permissions for user {:?} on {}/{}", |
@@ -261,7 +263,11 @@ impl GitBackend { | ||
261 | 263 | |
262 | 264 | if let Some(requester) = requester { |
263 | 265 | if !repository |
264 | .can_user_view_repository(&self.instance, Some(requester), &self.settings_provider) | |
266 | .can_user_view_repository( | |
267 | &self.instance, | |
268 | &Some(requester.clone()), | |
269 | &self.settings_provider, | |
270 | ) | |
265 | 271 | .await |
266 | 272 | { |
267 | 273 | return Err(GitBackendError::RepositoryNotFound { |
@@ -329,12 +335,18 @@ impl GitBackend { | ||
329 | 335 | |
330 | 336 | #[async_trait] |
331 | 337 | impl RepositoryBackend for GitBackend { |
332 | async fn exists(&mut self, repository: &Repository) -> Result<bool, Error> { | |
333 | if let Ok(_repository) = self | |
338 | async fn exists( | |
339 | &mut self, | |
340 | requester: &Option<AuthenticatedUser>, | |
341 | repository: &Repository, | |
342 | ) -> Result<bool, Error> { | |
343 | if let Ok(repository) = self | |
334 | 344 | .find_by_owner_user_name(&repository.owner.clone(), &repository.name) |
335 | 345 | .await |
336 | 346 | { |
337 | Ok(true) | |
347 | Ok(repository | |
348 | .can_user_view_repository(&self.instance, requester, &self.settings_provider) | |
349 | .await) | |
338 | 350 | } else { |
339 | 351 | Ok(false) |
340 | 352 | } |
@@ -342,7 +354,7 @@ impl RepositoryBackend for GitBackend { | ||
342 | 354 | |
343 | 355 | async fn create_repository( |
344 | 356 | &mut self, |
345 | _user: &User, | |
357 | _user: &AuthenticatedUser, | |
346 | 358 | request: &RepositoryCreateRequest, |
347 | 359 | ) -> Result<Repository, GitBackendError> { |
348 | 360 | // Check if repository already exists in the database |
@@ -491,7 +503,7 @@ impl RepositoryBackend for GitBackend { | ||
491 | 503 | |
492 | 504 | async fn repository_file_inspect( |
493 | 505 | &mut self, |
494 | requester: Option<&User>, | |
506 | requester: &Option<AuthenticatedUser>, | |
495 | 507 | repository: &Repository, |
496 | 508 | request: &RepositoryFileInspectRequest, |
497 | 509 | ) -> Result<Vec<RepositoryTreeEntry>, Error> { |
@@ -616,7 +628,7 @@ impl RepositoryBackend for GitBackend { | ||
616 | 628 | |
617 | 629 | async fn repository_file_from_id( |
618 | 630 | &mut self, |
619 | requester: Option<&User>, | |
631 | requester: &Option<AuthenticatedUser>, | |
620 | 632 | repository: &Repository, |
621 | 633 | request: &RepositoryFileFromIdRequest, |
622 | 634 | ) -> Result<RepositoryFile, Error> { |
@@ -647,7 +659,7 @@ impl RepositoryBackend for GitBackend { | ||
647 | 659 | |
648 | 660 | async fn repository_file_from_path( |
649 | 661 | &mut self, |
650 | requester: Option<&User>, | |
662 | requester: &Option<AuthenticatedUser>, | |
651 | 663 | repository: &Repository, |
652 | 664 | request: &RepositoryFileFromPathRequest, |
653 | 665 | ) -> Result<RepositoryFile, Error> { |
@@ -733,7 +745,7 @@ impl RepositoryBackend for GitBackend { | ||
733 | 745 | |
734 | 746 | async fn repository_diff( |
735 | 747 | &mut self, |
736 | requester: Option<&User>, | |
748 | requester: &Option<AuthenticatedUser>, | |
737 | 749 | repository: &Repository, |
738 | 750 | request: &RepositoryDiffRequest, |
739 | 751 | ) -> Result<RepositoryDiff, Error> { |
@@ -862,7 +874,7 @@ impl RepositoryBackend for GitBackend { | ||
862 | 874 | |
863 | 875 | async fn repository_diff_patch( |
864 | 876 | &mut self, |
865 | requester: Option<&User>, | |
877 | requester: &Option<AuthenticatedUser>, | |
866 | 878 | repository: &Repository, |
867 | 879 | request: &RepositoryDiffPatchRequest, |
868 | 880 | ) -> Result<String, Error> { |
@@ -917,7 +929,7 @@ impl RepositoryBackend for GitBackend { | ||
917 | 929 | |
918 | 930 | async fn repository_commit_before( |
919 | 931 | &mut self, |
920 | requester: Option<&User>, | |
932 | requester: &Option<AuthenticatedUser>, | |
921 | 933 | repository: &Repository, |
922 | 934 | request: &RepositoryCommitBeforeRequest, |
923 | 935 | ) -> Result<Commit, Error> { |
@@ -967,7 +979,7 @@ impl RepositoryBackend for GitBackend { | ||
967 | 979 | impl IssuesBackend for GitBackend { |
968 | 980 | fn issues_count( |
969 | 981 | &mut self, |
970 | _requester: Option<&User>, | |
982 | _requester: &Option<AuthenticatedUser>, | |
971 | 983 | _request: &RepositoryIssuesCountRequest, |
972 | 984 | ) -> Result<u64, Error> { |
973 | 985 | todo!() |
@@ -975,7 +987,7 @@ impl IssuesBackend for GitBackend { | ||
975 | 987 | |
976 | 988 | fn issue_labels( |
977 | 989 | &mut self, |
978 | _requester: Option<&User>, | |
990 | _requester: &Option<AuthenticatedUser>, | |
979 | 991 | _request: &RepositoryIssueLabelsRequest, |
980 | 992 | ) -> Result<Vec<IssueLabel>, Error> { |
981 | 993 | todo!() |
@@ -983,7 +995,7 @@ impl IssuesBackend for GitBackend { | ||
983 | 995 | |
984 | 996 | fn issues( |
985 | 997 | &mut self, |
986 | _requester: Option<&User>, | |
998 | _requester: &Option<AuthenticatedUser>, | |
987 | 999 | _request: &RepositoryIssuesRequest, |
988 | 1000 | ) -> Result<Vec<RepositoryIssue>, Error> { |
989 | 1001 | todo!() |
giterated-daemon/src/backend/mod.rs
@@ -6,6 +6,7 @@ pub mod user; | ||
6 | 6 | |
7 | 7 | use anyhow::Error; |
8 | 8 | use async_trait::async_trait; |
9 | use giterated_stack::AuthenticatedUser; | |
9 | 10 | use serde_json::Value; |
10 | 11 | |
11 | 12 | use crate::backend::git::GitBackendError; |
@@ -30,42 +31,42 @@ use giterated_models::value::AnyValue; | ||
30 | 31 | pub trait RepositoryBackend { |
31 | 32 | async fn create_repository( |
32 | 33 | &mut self, |
33 | user: &User, | |
34 | user: &AuthenticatedUser, | |
34 | 35 | request: &RepositoryCreateRequest, |
35 | 36 | ) -> Result<Repository, GitBackendError>; |
36 | 37 | async fn repository_file_inspect( |
37 | 38 | &mut self, |
38 | requester: Option<&User>, | |
39 | requester: &Option<AuthenticatedUser>, | |
39 | 40 | repository: &Repository, |
40 | 41 | request: &RepositoryFileInspectRequest, |
41 | 42 | ) -> Result<Vec<RepositoryTreeEntry>, Error>; |
42 | 43 | async fn repository_file_from_id( |
43 | 44 | &mut self, |
44 | requester: Option<&User>, | |
45 | requester: &Option<AuthenticatedUser>, | |
45 | 46 | repository: &Repository, |
46 | 47 | request: &RepositoryFileFromIdRequest, |
47 | 48 | ) -> Result<RepositoryFile, Error>; |
48 | 49 | async fn repository_file_from_path( |
49 | 50 | &mut self, |
50 | requester: Option<&User>, | |
51 | requester: &Option<AuthenticatedUser>, | |
51 | 52 | repository: &Repository, |
52 | 53 | request: &RepositoryFileFromPathRequest, |
53 | 54 | ) -> Result<RepositoryFile, Error>; |
54 | 55 | async fn repository_diff( |
55 | 56 | &mut self, |
56 | requester: Option<&User>, | |
57 | requester: &Option<AuthenticatedUser>, | |
57 | 58 | repository: &Repository, |
58 | 59 | request: &RepositoryDiffRequest, |
59 | 60 | ) -> Result<RepositoryDiff, Error>; |
60 | 61 | async fn repository_diff_patch( |
61 | 62 | &mut self, |
62 | requester: Option<&User>, | |
63 | requester: &Option<AuthenticatedUser>, | |
63 | 64 | repository: &Repository, |
64 | 65 | request: &RepositoryDiffPatchRequest, |
65 | 66 | ) -> Result<String, Error>; |
66 | 67 | async fn repository_commit_before( |
67 | 68 | &mut self, |
68 | requester: Option<&User>, | |
69 | requester: &Option<AuthenticatedUser>, | |
69 | 70 | repository: &Repository, |
70 | 71 | request: &RepositoryCommitBeforeRequest, |
71 | 72 | ) -> Result<Commit, Error>; |
@@ -81,23 +82,27 @@ pub trait RepositoryBackend { | ||
81 | 82 | name: &str, |
82 | 83 | setting: &Value, |
83 | 84 | ) -> Result<(), Error>; |
84 | async fn exists(&mut self, repository: &Repository) -> Result<bool, Error>; | |
85 | async fn exists( | |
86 | &mut self, | |
87 | requester: &Option<AuthenticatedUser>, | |
88 | repository: &Repository, | |
89 | ) -> Result<bool, Error>; | |
85 | 90 | } |
86 | 91 | |
87 | 92 | pub trait IssuesBackend { |
88 | 93 | fn issues_count( |
89 | 94 | &mut self, |
90 | requester: Option<&User>, | |
95 | requester: &Option<AuthenticatedUser>, | |
91 | 96 | request: &RepositoryIssuesCountRequest, |
92 | 97 | ) -> Result<u64, Error>; |
93 | 98 | fn issue_labels( |
94 | 99 | &mut self, |
95 | requester: Option<&User>, | |
100 | requester: &Option<AuthenticatedUser>, | |
96 | 101 | request: &RepositoryIssueLabelsRequest, |
97 | 102 | ) -> Result<Vec<IssueLabel>, Error>; |
98 | 103 | fn issues( |
99 | 104 | &mut self, |
100 | requester: Option<&User>, | |
105 | requester: &Option<AuthenticatedUser>, | |
101 | 106 | request: &RepositoryIssuesRequest, |
102 | 107 | ) -> Result<Vec<RepositoryIssue>, Error>; |
103 | 108 | } |
@@ -129,7 +134,7 @@ pub trait UserBackend: AuthBackend { | ||
129 | 134 | async fn exists(&mut self, user: &User) -> Result<bool, Error>; |
130 | 135 | async fn repositories_for_user( |
131 | 136 | &mut self, |
132 | requester: Option<&User>, | |
137 | requester: &Option<AuthenticatedUser>, | |
133 | 138 | user: &User, |
134 | 139 | ) -> Result<Vec<RepositorySummary>, Error>; |
135 | 140 | } |
giterated-daemon/src/backend/user.rs
@@ -8,6 +8,7 @@ use giterated_models::repository::{Repository, RepositorySummary}; | ||
8 | 8 | use giterated_models::settings::{AnySetting, Setting}; |
9 | 9 | use giterated_models::user::{Bio, DisplayName, User, UserParseError}; |
10 | 10 | use giterated_models::value::AnyValue; |
11 | use giterated_stack::AuthenticatedUser; | |
11 | 12 | use std::sync::Arc; |
12 | 13 | |
13 | 14 | use aes_gcm::{aead::Aead, AeadCore, Aes256Gcm, Key, KeyInit}; |
@@ -98,7 +99,7 @@ impl UserBackend for UserAuth { | ||
98 | 99 | |
99 | 100 | async fn repositories_for_user( |
100 | 101 | &mut self, |
101 | _requester: Option<&User>, | |
102 | _requester: &Option<AuthenticatedUser>, | |
102 | 103 | user: &User, |
103 | 104 | ) -> Result<Vec<RepositorySummary>, Error> { |
104 | 105 | let mut repositories = sqlx::query_as!( |
giterated-daemon/src/database_backend/handler.rs
@@ -19,7 +19,7 @@ use giterated_models::{ | ||
19 | 19 | user::{User, UserRepositoriesRequest}, |
20 | 20 | value::{AnyValue, GetValue}, |
21 | 21 | }; |
22 | use giterated_stack::{BackendWrapper, StackOperationState}; | |
22 | use giterated_stack::{AuthenticatedUser, BackendWrapper, StackOperationState}; | |
23 | 23 | |
24 | 24 | use super::DatabaseBackend; |
25 | 25 | |
@@ -27,16 +27,31 @@ pub fn user_get_repositories( | ||
27 | 27 | object: &User, |
28 | 28 | _operation: UserRepositoriesRequest, |
29 | 29 | state: DatabaseBackend, |
30 | operation_state: StackOperationState, | |
31 | requester: Option<AuthenticatedUser>, | |
30 | 32 | ) -> BoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> { |
31 | 33 | let object = object.clone(); |
32 | 34 | |
33 | 35 | async move { |
34 | 36 | let mut user_backend = state.user_backend.lock().await; |
35 | let repositories = user_backend | |
36 | .repositories_for_user(None, &object) | |
37 | let repositories_response = user_backend | |
38 | .repositories_for_user(&requester, &object) | |
37 | 39 | .await |
38 | 40 | .map_err(|e| OperationError::Internal(e.to_string()))?; |
39 | 41 | |
42 | let mut repositories = vec![]; | |
43 | ||
44 | for repository in repositories_response { | |
45 | if operation_state | |
46 | .giterated_backend | |
47 | .get_object::<Repository>(&repository.repository.to_string(), &operation_state) | |
48 | .await | |
49 | .is_ok() | |
50 | { | |
51 | repositories.push(repository); | |
52 | } | |
53 | } | |
54 | ||
40 | 55 | Ok(repositories) |
41 | 56 | } |
42 | 57 | .boxed() |
@@ -105,6 +120,7 @@ pub fn repository_info( | ||
105 | 120 | state: DatabaseBackend, |
106 | 121 | operation_state: StackOperationState, |
107 | 122 | backend: BackendWrapper, |
123 | requester: Option<AuthenticatedUser>, | |
108 | 124 | ) -> BoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> { |
109 | 125 | let object = object.clone(); |
110 | 126 | |
@@ -117,7 +133,7 @@ pub fn repository_info( | ||
117 | 133 | let mut repository_backend = state.repository_backend.lock().await; |
118 | 134 | let tree = repository_backend |
119 | 135 | .repository_file_inspect( |
120 | None, | |
136 | &requester, | |
121 | 137 | object.object(), |
122 | 138 | &RepositoryFileInspectRequest { |
123 | 139 | extra_metadata: operation.extra_metadata, |
@@ -158,6 +174,7 @@ pub fn repository_file_from_id( | ||
158 | 174 | state: DatabaseBackend, |
159 | 175 | operation_state: StackOperationState, |
160 | 176 | backend: BackendWrapper, |
177 | requester: Option<AuthenticatedUser>, | |
161 | 178 | ) -> BoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> { |
162 | 179 | let object = object.clone(); |
163 | 180 | |
@@ -170,7 +187,7 @@ pub fn repository_file_from_id( | ||
170 | 187 | let mut repository_backend = state.repository_backend.lock().await; |
171 | 188 | let file = repository_backend |
172 | 189 | .repository_file_from_id( |
173 | None, | |
190 | &requester, | |
174 | 191 | object.object(), |
175 | 192 | &RepositoryFileFromIdRequest(operation.0), |
176 | 193 | ) |
@@ -189,6 +206,7 @@ pub fn repository_file_from_path( | ||
189 | 206 | state: DatabaseBackend, |
190 | 207 | operation_state: StackOperationState, |
191 | 208 | backend: BackendWrapper, |
209 | requester: Option<AuthenticatedUser>, | |
192 | 210 | ) -> BoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> { |
193 | 211 | let object = object.clone(); |
194 | 212 | |
@@ -201,7 +219,7 @@ pub fn repository_file_from_path( | ||
201 | 219 | let mut repository_backend = state.repository_backend.lock().await; |
202 | 220 | let file = repository_backend |
203 | 221 | .repository_file_from_path( |
204 | None, | |
222 | &requester, | |
205 | 223 | object.object(), |
206 | 224 | &RepositoryFileFromPathRequest { |
207 | 225 | rev: operation.rev, |
@@ -223,6 +241,7 @@ pub fn repository_diff( | ||
223 | 241 | state: DatabaseBackend, |
224 | 242 | operation_state: StackOperationState, |
225 | 243 | backend: BackendWrapper, |
244 | requester: Option<AuthenticatedUser>, | |
226 | 245 | ) -> BoxFuture<'static, Result<RepositoryDiff, OperationError<RepositoryError>>> { |
227 | 246 | let object = object.clone(); |
228 | 247 | |
@@ -234,7 +253,7 @@ pub fn repository_diff( | ||
234 | 253 | |
235 | 254 | let mut repository_backend = state.repository_backend.lock().await; |
236 | 255 | let diff = repository_backend |
237 | .repository_diff(None, object.object(), &operation) | |
256 | .repository_diff(&requester, object.object(), &operation) | |
238 | 257 | .await |
239 | 258 | .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; |
240 | 259 | drop(repository_backend); |
@@ -250,6 +269,7 @@ pub fn repository_diff_patch( | ||
250 | 269 | state: DatabaseBackend, |
251 | 270 | operation_state: StackOperationState, |
252 | 271 | backend: BackendWrapper, |
272 | requester: Option<AuthenticatedUser>, | |
253 | 273 | ) -> BoxFuture<'static, Result<String, OperationError<RepositoryError>>> { |
254 | 274 | let object = object.clone(); |
255 | 275 | |
@@ -261,7 +281,7 @@ pub fn repository_diff_patch( | ||
261 | 281 | |
262 | 282 | let mut repository_backend = state.repository_backend.lock().await; |
263 | 283 | let patch = repository_backend |
264 | .repository_diff_patch(None, object.object(), &operation) | |
284 | .repository_diff_patch(&requester, object.object(), &operation) | |
265 | 285 | .await |
266 | 286 | .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; |
267 | 287 | drop(repository_backend); |
@@ -277,6 +297,7 @@ pub fn repository_commit_before( | ||
277 | 297 | state: DatabaseBackend, |
278 | 298 | operation_state: StackOperationState, |
279 | 299 | backend: BackendWrapper, |
300 | requester: Option<AuthenticatedUser>, | |
280 | 301 | ) -> BoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> { |
281 | 302 | let object = object.clone(); |
282 | 303 | |
@@ -288,7 +309,7 @@ pub fn repository_commit_before( | ||
288 | 309 | |
289 | 310 | let mut repository_backend = state.repository_backend.lock().await; |
290 | 311 | let file = repository_backend |
291 | .repository_commit_before(None, object.object(), &operation) | |
312 | .repository_commit_before(&requester, object.object(), &operation) | |
292 | 313 | .await |
293 | 314 | .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; |
294 | 315 | drop(repository_backend); |
@@ -394,12 +415,13 @@ pub fn instance_create_repository_request( | ||
394 | 415 | _object: &Instance, |
395 | 416 | operation: RepositoryCreateRequest, |
396 | 417 | state: DatabaseBackend, |
418 | requester: AuthenticatedUser, | |
397 | 419 | ) -> BoxFuture<'static, Result<Repository, OperationError<InstanceError>>> { |
398 | 420 | async move { |
399 | 421 | let mut backend = state.repository_backend.lock().await; |
400 | 422 | |
401 | 423 | backend |
402 | .create_repository(&operation.owner, &operation) | |
424 | .create_repository(&requester, &operation) | |
403 | 425 | .await |
404 | 426 | .map_err(|e| OperationError::Internal(e.to_string())) |
405 | 427 | } |
giterated-daemon/src/database_backend/mod.rs
@@ -131,7 +131,7 @@ mod test { | ||
131 | 131 | use giterated_models::user::{DisplayName, User}; |
132 | 132 | use giterated_models::value::{AnyValue, GiteratedObjectValue}; |
133 | 133 | use giterated_stack::handler::GiteratedBackend; |
134 | use giterated_stack::StackOperationState; | |
134 | use giterated_stack::{AuthenticatedUser, StackOperationState}; | |
135 | 135 | use serde_json::Value; |
136 | 136 | use tokio::sync::Mutex; |
137 | 137 | |
@@ -169,7 +169,7 @@ mod test { | ||
169 | 169 | } |
170 | 170 | async fn repositories_for_user( |
171 | 171 | &mut self, |
172 | _requester: Option<&User>, | |
172 | _requester: &Option<AuthenticatedUser>, | |
173 | 173 | _user: &User, |
174 | 174 | ) -> Result<Vec<RepositorySummary>, Error> { |
175 | 175 | todo!() |
@@ -200,14 +200,14 @@ mod test { | ||
200 | 200 | impl RepositoryBackend for TestUserRepositoryBackend { |
201 | 201 | async fn create_repository( |
202 | 202 | &mut self, |
203 | _user: &User, | |
203 | _user: &AuthenticatedUser, | |
204 | 204 | _request: &RepositoryCreateRequest, |
205 | 205 | ) -> Result<Repository, GitBackendError> { |
206 | 206 | todo!() |
207 | 207 | } |
208 | 208 | async fn repository_file_inspect( |
209 | 209 | &mut self, |
210 | _requester: Option<&User>, | |
210 | _requester: &Option<AuthenticatedUser>, | |
211 | 211 | _repository: &Repository, |
212 | 212 | _request: &RepositoryFileInspectRequest, |
213 | 213 | ) -> Result<Vec<RepositoryTreeEntry>, Error> { |
@@ -215,7 +215,7 @@ mod test { | ||
215 | 215 | } |
216 | 216 | async fn repository_file_from_id( |
217 | 217 | &mut self, |
218 | _requester: Option<&User>, | |
218 | _requester: &Option<AuthenticatedUser>, | |
219 | 219 | _repository: &Repository, |
220 | 220 | _request: &RepositoryFileFromIdRequest, |
221 | 221 | ) -> Result<RepositoryFile, Error> { |
@@ -223,7 +223,7 @@ mod test { | ||
223 | 223 | } |
224 | 224 | async fn repository_file_from_path( |
225 | 225 | &mut self, |
226 | _requester: Option<&User>, | |
226 | _requester: &Option<AuthenticatedUser>, | |
227 | 227 | _repository: &Repository, |
228 | 228 | _request: &RepositoryFileFromPathRequest, |
229 | 229 | ) -> Result<RepositoryFile, Error> { |
@@ -231,7 +231,7 @@ mod test { | ||
231 | 231 | } |
232 | 232 | async fn repository_diff( |
233 | 233 | &mut self, |
234 | _requester: Option<&User>, | |
234 | _requester: &Option<AuthenticatedUser>, | |
235 | 235 | _repository: &Repository, |
236 | 236 | _request: &RepositoryDiffRequest, |
237 | 237 | ) -> Result<RepositoryDiff, Error> { |
@@ -239,7 +239,7 @@ mod test { | ||
239 | 239 | } |
240 | 240 | async fn repository_diff_patch( |
241 | 241 | &mut self, |
242 | _requester: Option<&User>, | |
242 | _requester: &Option<AuthenticatedUser>, | |
243 | 243 | _repository: &Repository, |
244 | 244 | _request: &RepositoryDiffPatchRequest, |
245 | 245 | ) -> Result<String, Error> { |
@@ -247,7 +247,7 @@ mod test { | ||
247 | 247 | } |
248 | 248 | async fn repository_commit_before( |
249 | 249 | &mut self, |
250 | _requester: Option<&User>, | |
250 | _requester: &Option<AuthenticatedUser>, | |
251 | 251 | _repository: &Repository, |
252 | 252 | _request: &RepositoryCommitBeforeRequest, |
253 | 253 | ) -> Result<Commit, Error> { |
@@ -282,7 +282,11 @@ mod test { | ||
282 | 282 | Ok(()) |
283 | 283 | } |
284 | 284 | |
285 | async fn exists(&mut self, repository: &Repository) -> Result<bool, Error> { | |
285 | async fn exists( | |
286 | &mut self, | |
287 | _requester: &Option<AuthenticatedUser>, | |
288 | repository: &Repository, | |
289 | ) -> Result<bool, Error> { | |
286 | 290 | // Ok(true) |
287 | 291 | Ok(repository |
288 | 292 | == &Repository::from_str( |
giterated-models/src/repository/settings.rs
@@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; | ||
2 | 2 | |
3 | 3 | use crate::{settings::Setting, user::User}; |
4 | 4 | |
5 | use super::{DefaultBranch, RepositoryVisibility}; | |
5 | use super::DefaultBranch; | |
6 | 6 | |
7 | 7 | impl Setting for DefaultBranch { |
8 | 8 | fn name() -> &'static str { |
giterated-stack/src/lib.rs
@@ -297,6 +297,57 @@ where | ||
297 | 297 | } |
298 | 298 | } |
299 | 299 | |
300 | #[async_trait::async_trait] | |
301 | impl<O, O1, O2, O3, D, F, S> GiteratedOperationHandler<(O1, O2, O3), O, D, S> for F | |
302 | where | |
303 | F: FnMut( | |
304 | &O, | |
305 | D, | |
306 | S, | |
307 | O1, | |
308 | O2, | |
309 | O3, | |
310 | ) -> Pin< | |
311 | Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>, | |
312 | > + Send | |
313 | + Sync | |
314 | + Clone, | |
315 | O: GiteratedObject + Send + Sync, | |
316 | D: GiteratedOperation<O> + 'static, | |
317 | <D as GiteratedOperation<O>>::Failure: Send, | |
318 | S: Send + Sync + Clone + 'static, | |
319 | O1: FromOperationState, | |
320 | O2: FromOperationState, | |
321 | O3: FromOperationState, | |
322 | { | |
323 | fn operation_name(&self) -> &str { | |
324 | D::operation_name() | |
325 | } | |
326 | ||
327 | fn object_name(&self) -> &str { | |
328 | O::object_name() | |
329 | } | |
330 | ||
331 | async fn handle( | |
332 | &self, | |
333 | object: &O, | |
334 | operation: D, | |
335 | state: S, | |
336 | operation_state: &StackOperationState, | |
337 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
338 | let o1 = O1::from_state(operation_state) | |
339 | .await | |
340 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
341 | let o2 = O2::from_state(operation_state) | |
342 | .await | |
343 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
344 | let o3 = O3::from_state(operation_state) | |
345 | .await | |
346 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
347 | self.clone()(object, operation, state, o1, o2, o3).await | |
348 | } | |
349 | } | |
350 | ||
300 | 351 | pub struct OperationWrapper<S: Send + Sync + Clone> { |
301 | 352 | func: Box< |
302 | 353 | dyn Fn( |
@@ -391,6 +442,43 @@ impl FromOperationState for StackOperationState { | ||
391 | 442 | } |
392 | 443 | } |
393 | 444 | |
445 | #[async_trait::async_trait] | |
446 | impl FromOperationState for AuthenticatedUser { | |
447 | type Error = (); | |
448 | ||
449 | async fn from_state( | |
450 | state: &StackOperationState, | |
451 | ) -> Result<AuthenticatedUser, OperationError<()>> { | |
452 | state | |
453 | .user | |
454 | .clone() | |
455 | .ok_or_else(|| OperationError::Operation(())) | |
456 | } | |
457 | } | |
458 | ||
459 | #[async_trait::async_trait] | |
460 | impl FromOperationState for AuthenticatedInstance { | |
461 | type Error = (); | |
462 | ||
463 | async fn from_state( | |
464 | state: &StackOperationState, | |
465 | ) -> Result<AuthenticatedInstance, OperationError<()>> { | |
466 | state | |
467 | .instance | |
468 | .clone() | |
469 | .ok_or_else(|| OperationError::Operation(())) | |
470 | } | |
471 | } | |
472 | ||
473 | #[async_trait::async_trait] | |
474 | impl<T: FromOperationState> FromOperationState for Option<T> { | |
475 | type Error = (); | |
476 | ||
477 | async fn from_state(state: &StackOperationState) -> Result<Option<T>, OperationError<()>> { | |
478 | Ok(T::from_state(state).await.ok()) | |
479 | } | |
480 | } | |
481 | ||
394 | 482 | #[derive(Clone)] |
395 | 483 | pub struct StackOperationState { |
396 | 484 | pub giterated_backend: BackendWrapper, |