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

ambee/giterated

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

Incomplete repository branches request

erremilia - ⁨2⁩ years ago

parent: tbd commit: ⁨6872fbf

⁨giterated-daemon/src/database_backend/mod.rs⁩ - ⁨15439⁩ bytes
Raw
1 pub mod handler;
2
3 use std::sync::Arc;
4
5 use giterated_models::error::OperationError;
6 use giterated_models::instance::Instance;
7 use giterated_models::object::{GiteratedObject, Object, ObjectRequestError};
8 use giterated_models::object_backend::ObjectBackend;
9 use giterated_models::operation::GiteratedOperation;
10 use giterated_models::repository::Repository;
11 use giterated_models::user::User;
12 use giterated_stack::handler::GiteratedBackend;
13 use giterated_stack::{OperationHandlers, StackOperationState};
14 use std::fmt::Debug;
15 use tokio::sync::Mutex;
16
17 use crate::backend::{RepositoryBackend, UserBackend};
18
19 use self::handler::{
20 instance_authentication_request, instance_create_repository_request,
21 instance_registration_request, repository_commit_before, repository_diff,
22 repository_diff_patch, repository_file_from_id, repository_file_from_path,
23 repository_get_setting, repository_get_value, repository_info, repository_set_setting,
24 user_get_repositories, user_get_setting, user_get_value, user_set_setting, repository_commit_by_id, repository_last_commit_of_file, repository_get_statistics, repository_get_branches,
25 };
26
27 #[derive(Clone, Debug)]
28 pub struct Foobackend {}
29
30 #[async_trait::async_trait]
31 impl ObjectBackend<StackOperationState> for Foobackend {
32 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
33 &self,
34 _object: O,
35 _operation: &str,
36 _payload: D,
37 _operation_state: &StackOperationState,
38 ) -> Result<D::Success, OperationError<D::Failure>> {
39 // We don't handle operations with this backend
40 Err(OperationError::Unhandled)
41 }
42
43 async fn get_object<O: GiteratedObject + Debug>(
44 &self,
45 _object_str: &str,
46 _operation_state: &StackOperationState,
47 ) -> Result<Object<StackOperationState, O, Self>, OperationError<ObjectRequestError>> {
48 Err(OperationError::Unhandled)
49 }
50 }
51
52 /// A backend implementation which attempts to resolve data from the instance's database.
53 #[derive(Clone)]
54 pub struct DatabaseBackend {
55 pub(self) our_instance: Instance,
56 pub(self) user_backend: Arc<Mutex<dyn UserBackend + Send>>,
57 pub(self) repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>>,
58 }
59
60 impl DatabaseBackend {
61 pub fn new(
62 instance: Instance,
63 user_backend: Arc<Mutex<dyn UserBackend + Send>>,
64 repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>>,
65 ) -> Self {
66 Self {
67 our_instance: instance,
68 user_backend,
69 repository_backend,
70 }
71 }
72
73 pub fn into_backend(&self) -> GiteratedBackend<Self> {
74 let mut handlers = OperationHandlers::default();
75
76 handlers
77 .insert(user_get_repositories)
78 .insert(user_get_value)
79 .insert(user_get_setting)
80 .insert(user_set_setting)
81 .insert(repository_info)
82 .insert(repository_get_statistics)
83 .insert(repository_file_from_id)
84 .insert(repository_file_from_path)
85 .insert(repository_last_commit_of_file)
86 .insert(repository_commit_by_id)
87 .insert(repository_diff)
88 .insert(repository_diff_patch)
89 .insert(repository_commit_before)
90 .insert(repository_get_branches)
91 .insert(repository_get_value)
92 .insert(repository_get_setting)
93 .insert(repository_set_setting)
94 .insert(instance_registration_request)
95 .insert(instance_authentication_request)
96 .insert(instance_create_repository_request)
97 .register_object::<Instance>()
98 .register_object::<Repository>()
99 .register_object::<User>();
100
101 GiteratedBackend::new(self.clone(), handlers)
102 }
103 }
104
105 impl Debug for DatabaseBackend {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("DatabaseBackend").finish()
108 }
109 }
110
111 // TODO: These should be on the stack
112 // These tests verify that the essential handling of the database backend is
113 // functional and correct.
114 #[cfg(test)]
115 mod test {
116 use std::{str::FromStr, sync::Arc};
117
118 use anyhow::Error;
119
120 use giterated_models::authenticated::UserAuthenticationToken;
121
122 use giterated_models::instance::{
123 AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest,
124 };
125
126 use giterated_models::object_backend::ObjectBackend;
127
128 use giterated_models::repository::{
129 Commit, Description, Repository, RepositoryCommitBeforeRequest, RepositoryDiff,
130 RepositoryDiffPatchRequest, RepositoryDiffRequest, RepositoryFile,
131 RepositoryFileFromIdRequest, RepositoryFileFromPathRequest, RepositoryFileInspectRequest,
132 RepositorySummary, RepositoryTreeEntry, RepositoryCommitFromIdRequest, RepositoryLastCommitOfFileRequest, RepositoryStatisticsRequest, RepositoryStatistics, RepositoryBranch, RepositoryBranchesRequest,
133 };
134 use giterated_models::settings::AnySetting;
135 use giterated_models::user::{DisplayName, User};
136 use giterated_models::value::{AnyValue, GiteratedObjectValue};
137 use giterated_stack::handler::GiteratedBackend;
138 use giterated_stack::{AuthenticatedUser, StackOperationState};
139 use serde_json::Value;
140 use tokio::sync::Mutex;
141
142 use crate::backend::{git::GitBackendError, AuthBackend, RepositoryBackend, UserBackend};
143
144 use super::DatabaseBackend;
145 pub struct TestUserDatabaseBackend;
146
147 #[async_trait::async_trait]
148 impl UserBackend for TestUserDatabaseBackend {
149 async fn get_value(&mut self, _user: &User, name: &str) -> Result<AnyValue<User>, Error> {
150 assert_eq!(name, DisplayName::value_name());
151
152 Ok(serde_json::from_slice(
153 &serde_json::to_vec(&DisplayName(String::from("test"))).unwrap(),
154 )
155 .unwrap())
156 }
157 async fn get_setting(&mut self, _user: &User, _name: &str) -> Result<AnySetting, Error> {
158 Ok(serde_json::from_slice(
159 &serde_json::to_vec(&DisplayName(String::from("test"))).unwrap(),
160 )
161 .unwrap())
162 }
163 async fn write_setting(
164 &mut self,
165 _user: &User,
166 _name: &str,
167 _setting: &Value,
168 ) -> Result<(), Error> {
169 Ok(())
170 }
171 async fn exists(&mut self, user: &User) -> Result<bool, Error> {
172 Ok(user == &User::from_str("test_user:test.giterated.dev").unwrap())
173 }
174 async fn repositories_for_user(
175 &mut self,
176 _requester: &Option<AuthenticatedUser>,
177 _user: &User,
178 ) -> Result<Vec<RepositorySummary>, Error> {
179 todo!()
180 }
181 }
182
183 #[async_trait::async_trait]
184 impl AuthBackend for TestUserDatabaseBackend {
185 async fn register(
186 &mut self,
187 _request: RegisterAccountRequest,
188 ) -> Result<UserAuthenticationToken, Error> {
189 todo!()
190 }
191
192 async fn login(
193 &mut self,
194 _source: &Instance,
195 _request: AuthenticationTokenRequest,
196 ) -> Result<UserAuthenticationToken, Error> {
197 todo!()
198 }
199 }
200
201 pub struct TestUserRepositoryBackend;
202
203 #[async_trait::async_trait]
204 impl RepositoryBackend for TestUserRepositoryBackend {
205 async fn create_repository(
206 &mut self,
207 _user: &AuthenticatedUser,
208 _request: &RepositoryCreateRequest,
209 ) -> Result<Repository, GitBackendError> {
210 todo!()
211 }
212 async fn repository_file_inspect(
213 &mut self,
214 _requester: &Option<AuthenticatedUser>,
215 _repository: &Repository,
216 _request: &RepositoryFileInspectRequest,
217 ) -> Result<Vec<RepositoryTreeEntry>, Error> {
218 todo!()
219 }
220 async fn repository_file_from_id(
221 &mut self,
222 _requester: &Option<AuthenticatedUser>,
223 _repository: &Repository,
224 _request: &RepositoryFileFromIdRequest,
225 ) -> Result<RepositoryFile, Error> {
226 todo!()
227 }
228 async fn repository_file_from_path(
229 &mut self,
230 _requester: &Option<AuthenticatedUser>,
231 _repository: &Repository,
232 _request: &RepositoryFileFromPathRequest,
233 ) -> Result<(RepositoryFile, String), Error> {
234 todo!()
235 }
236 async fn repository_last_commit_of_file(
237 &mut self,
238 _requester: &Option<AuthenticatedUser>,
239 _repository: &Repository,
240 _request: &RepositoryLastCommitOfFileRequest,
241 ) -> Result<Commit, Error> {
242 todo!()
243 }
244 async fn repository_commit_from_id(
245 &mut self,
246 _requester: &Option<AuthenticatedUser>,
247 _repository: &Repository,
248 _request: &RepositoryCommitFromIdRequest,
249 ) -> Result<Commit, Error> {
250 todo!()
251 }
252 async fn repository_diff(
253 &mut self,
254 _requester: &Option<AuthenticatedUser>,
255 _repository: &Repository,
256 _request: &RepositoryDiffRequest,
257 ) -> Result<RepositoryDiff, Error> {
258 todo!()
259 }
260 async fn repository_diff_patch(
261 &mut self,
262 _requester: &Option<AuthenticatedUser>,
263 _repository: &Repository,
264 _request: &RepositoryDiffPatchRequest,
265 ) -> Result<String, Error> {
266 todo!()
267 }
268 async fn repository_commit_before(
269 &mut self,
270 _requester: &Option<AuthenticatedUser>,
271 _repository: &Repository,
272 _request: &RepositoryCommitBeforeRequest,
273 ) -> Result<Commit, Error> {
274 todo!()
275 }
276 async fn repository_get_statistics(
277 &mut self,
278 _requester: &Option<AuthenticatedUser>,
279 _repository: &Repository,
280 _request: &RepositoryStatisticsRequest,
281 ) -> Result<RepositoryStatistics, Error> {
282 todo!()
283 }
284 async fn repository_get_branches(
285 &mut self,
286 _requester: &Option<AuthenticatedUser>,
287 _repository: &Repository,
288 _request: &RepositoryBranchesRequest,
289 ) -> Result<Vec<RepositoryBranch>, Error> {
290 todo!()
291 }
292 async fn get_value(
293 &mut self,
294 _repository: &Repository,
295 _name: &str,
296 ) -> Result<AnyValue<Repository>, Error> {
297 Ok(serde_json::from_slice(
298 &serde_json::to_vec(&Description(String::from("test"))).unwrap(),
299 )
300 .unwrap())
301 }
302 async fn get_setting(
303 &mut self,
304 _repository: &Repository,
305 _name: &str,
306 ) -> Result<AnySetting, Error> {
307 Ok(serde_json::from_slice(
308 &serde_json::to_vec(&Description(String::from("test"))).unwrap(),
309 )
310 .unwrap())
311 }
312 async fn write_setting(
313 &mut self,
314 _repository: &Repository,
315 _name: &str,
316 _setting: &Value,
317 ) -> Result<(), Error> {
318 Ok(())
319 }
320
321 async fn exists(
322 &mut self,
323 _requester: &Option<AuthenticatedUser>,
324 repository: &Repository,
325 ) -> Result<bool, Error> {
326 // Ok(true)
327 Ok(repository
328 == &Repository::from_str(
329 "test_user:test.giterated.dev/[email protected]",
330 )
331 .unwrap())
332 }
333 }
334
335 fn test_backend() -> GiteratedBackend<DatabaseBackend> {
336 DatabaseBackend {
337 our_instance: Instance::from_str("testing.giterated.dev").unwrap(),
338 user_backend: Arc::new(Mutex::new(TestUserDatabaseBackend)) as _,
339 repository_backend: Arc::new(Mutex::new(TestUserRepositoryBackend)) as _,
340 }
341 .into_backend()
342 }
343
344 fn operation_state() -> StackOperationState {
345 todo!()
346 }
347
348 #[tokio::test]
349 async fn test_user_get() {
350 let backend = test_backend();
351 let operation_state = operation_state();
352
353 let mut user = backend
354 .get_object::<User>("test_user:test.giterated.dev", &operation_state)
355 .await
356 .expect("object should have been returned");
357
358 user.get::<DisplayName>(&operation_state)
359 .await
360 .expect("object value should have been returned");
361 }
362
363 #[tokio::test]
364 async fn test_user_get_setting() {
365 let backend = test_backend();
366 let operation_state = operation_state();
367
368 let mut user = backend
369 .get_object::<User>("test_user:test.giterated.dev", &operation_state)
370 .await
371 .expect("object should have been returned");
372
373 user.get_setting::<DisplayName>(&operation_state)
374 .await
375 .expect("object value should have been returned");
376 }
377
378 #[tokio::test]
379 async fn test_user_set_setting() {
380 let backend = test_backend();
381 let operation_state = operation_state();
382
383 let mut user = backend
384 .get_object::<User>("test_user:test.giterated.dev", &operation_state)
385 .await
386 .expect("object should have been returned");
387
388 user.set_setting::<DisplayName>(DisplayName(String::from("test")), &operation_state)
389 .await
390 .expect("object value should have been returned");
391 }
392
393 #[tokio::test]
394 async fn test_respository_get() {
395 let backend = test_backend();
396 let operation_state = operation_state();
397
398 let mut repository = backend
399 .get_object::<Repository>(
400 "test_user:test.giterated.dev/[email protected]",
401 &operation_state,
402 )
403 .await
404 .expect("object should have been returned");
405
406 repository
407 .get::<Description>(&operation_state)
408 .await
409 .expect("object value should have been returned");
410 }
411
412 #[tokio::test]
413 async fn test_repository_get_setting() {
414 let backend = test_backend();
415 let operation_state = operation_state();
416
417 let mut repository = backend
418 .get_object::<Repository>(
419 "test_user:test.giterated.dev/[email protected]",
420 &operation_state,
421 )
422 .await
423 .expect("object should have been returned");
424
425 repository
426 .get_setting::<Description>(&operation_state)
427 .await
428 .expect("object value should have been returned");
429 }
430
431 #[tokio::test]
432 async fn test_repository_set_setting() {
433 let backend = test_backend();
434 let operation_state = operation_state();
435
436 let mut repository = backend
437 .get_object::<Repository>(
438 "test_user:test.giterated.dev/[email protected]",
439 &operation_state,
440 )
441 .await
442 .expect("object should have been returned");
443
444 repository
445 .set_setting::<Description>(Description(String::from("test")), &operation_state)
446 .await
447 .expect("object value should have been returned");
448 }
449 }
450