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

ambee/giterated

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

Unified stack `GetValue` implementation

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨325f5af

⁨giterated-daemon/src/database_backend/handler.rs⁩ - ⁨21697⁩ bytes
Raw
1 use std::{error::Error, sync::Arc};
2
3 use futures_util::{future::LocalBoxFuture, FutureExt};
4 use giterated_models::{
5 authenticated::UserAuthenticationToken,
6 error::{GetValueError, InstanceError, OperationError, RepositoryError, UserError},
7 instance::{
8 AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest,
9 },
10 object_backend::ObjectBackend,
11 repository::{
12 Commit, DefaultBranch, Description, LatestCommit, Repository, RepositoryBranch,
13 RepositoryBranchesRequest, RepositoryCommitBeforeRequest, RepositoryCommitFromIdRequest,
14 RepositoryDiff, RepositoryDiffPatchRequest, RepositoryDiffRequest, RepositoryFile,
15 RepositoryFileFromIdRequest, RepositoryFileFromPathRequest, RepositoryFileInspectRequest,
16 RepositoryInfoRequest, RepositoryLastCommitOfFileRequest, RepositoryStatistics,
17 RepositoryStatisticsRequest, RepositorySummary, RepositoryView, Visibility,
18 },
19 settings::{AnySetting, GetSetting, GetSettingError},
20 user::{Bio, DisplayName, User, UserRepositoriesRequest},
21 value::{AnyValue, GetValueTyped},
22 };
23 use giterated_stack::{AuthenticatedUser, AuthorizedInstance, GiteratedStack, StackOperationState};
24
25 use super::DatabaseBackend;
26
27 pub fn user_get_repositories(
28 object: &User,
29 _operation: UserRepositoriesRequest,
30 state: DatabaseBackend,
31 _operation_state: StackOperationState,
32 requester: Option<AuthenticatedUser>,
33 ) -> LocalBoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> {
34 let object = object.clone();
35
36 async move {
37 let mut user_backend = state.user_backend.lock().await;
38 let repositories_response = user_backend
39 .repositories_for_user(&requester, &object)
40 .await
41 .map_err(|e| OperationError::Internal(e.to_string()))?;
42 drop(user_backend);
43 let mut repositories_backend = state.repository_backend.lock().await;
44
45 let mut repositories = vec![];
46
47 for repository in repositories_response {
48 if repositories_backend
49 .exists(&requester, &repository.repository)
50 .await
51 .map_err(|e| OperationError::Internal(e.to_string()))?
52 {
53 repositories.push(repository);
54 }
55 }
56
57 Ok(repositories)
58 }
59 .boxed_local()
60 }
61
62 pub fn user_get_value(
63 object: &User,
64 operation: GetValueTyped<AnyValue<User>>,
65 state: DatabaseBackend,
66 ) -> LocalBoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> {
67 let object = object.clone();
68
69 async move {
70 let mut user_backend = state.user_backend.lock().await;
71 let value = user_backend
72 .get_value(&object, &operation.value_name)
73 .await
74 .map_err(|e| OperationError::Internal(e.to_string()))?;
75
76 Ok(value)
77 }
78 .boxed_local()
79 }
80
81 pub fn user_get_setting(
82 object: &User,
83 operation: GetSetting,
84 state: DatabaseBackend,
85 ) -> LocalBoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
86 let object = object.clone();
87
88 async move {
89 let mut user_backend = state.user_backend.lock().await;
90 let value = user_backend
91 .get_setting(&object, &operation.setting_name)
92 .await
93 .map_err(|e| OperationError::Internal(e.to_string()))?;
94
95 Ok(value)
96 }
97 .boxed_local()
98 }
99
100 pub fn repository_info(
101 object: &Repository,
102 operation: RepositoryInfoRequest,
103 state: DatabaseBackend,
104 operation_state: StackOperationState,
105 backend: Arc<GiteratedStack>,
106 requester: Option<AuthenticatedUser>,
107 ) -> LocalBoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> {
108 let object = object.clone();
109
110 async move {
111 let mut object = backend
112 .get_object::<Repository>(&object.to_string(), &operation_state)
113 .await
114 .unwrap();
115 let mut repository_backend = state.repository_backend.lock().await;
116 let tree = repository_backend
117 .repository_file_inspect(
118 &requester,
119 object.object(),
120 &RepositoryFileInspectRequest {
121 extra_metadata: operation.extra_metadata,
122 path: operation.path,
123 rev: operation.rev.clone(),
124 },
125 )
126 .await
127 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
128
129 let statistics = repository_backend
130 .repository_get_statistics(
131 &requester,
132 object.object(),
133 &RepositoryStatisticsRequest {
134 rev: operation.rev.clone(),
135 },
136 )
137 .await
138 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
139 drop(repository_backend);
140
141 let info = RepositoryView {
142 name: object.object().name.clone(),
143 owner: object.object().owner.clone(),
144 description: object.get::<Description>(&operation_state).await.ok(),
145 visibility: object
146 .get::<Visibility>(&operation_state)
147 .await
148 .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?,
149 default_branch: object
150 .get::<DefaultBranch>(&operation_state)
151 .await
152 .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?,
153 // TODO: Can't be a simple get function, this needs to be returned alongside the tree as this differs depending on the rev and path.
154 latest_commit: object.get::<LatestCommit>(&operation_state).await.ok(),
155 stats: statistics,
156 tree_rev: operation.rev,
157 tree,
158 };
159
160 Ok(info)
161 }
162 .boxed_local()
163 }
164
165 pub fn repository_get_statistics(
166 object: &Repository,
167 operation: RepositoryStatisticsRequest,
168 state: DatabaseBackend,
169 operation_state: StackOperationState,
170 backend: Arc<GiteratedStack>,
171 requester: Option<AuthenticatedUser>,
172 ) -> LocalBoxFuture<'static, Result<RepositoryStatistics, OperationError<RepositoryError>>> {
173 let object = object.clone();
174
175 async move {
176 let object = backend
177 .get_object::<Repository>(&object.to_string(), &operation_state)
178 .await
179 .unwrap();
180
181 let mut repository_backend = state.repository_backend.lock().await;
182 let statistics = repository_backend
183 .repository_get_statistics(
184 &requester,
185 object.object(),
186 &RepositoryStatisticsRequest { rev: operation.rev },
187 )
188 .await
189 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
190 drop(repository_backend);
191
192 Ok(statistics)
193 }
194 .boxed_local()
195 }
196
197 pub fn repository_get_branches(
198 object: &Repository,
199 operation: RepositoryBranchesRequest,
200 state: DatabaseBackend,
201 operation_state: StackOperationState,
202 backend: Arc<GiteratedStack>,
203 requester: Option<AuthenticatedUser>,
204 ) -> LocalBoxFuture<'static, Result<Vec<RepositoryBranch>, OperationError<RepositoryError>>> {
205 let object = object.clone();
206
207 async move {
208 let object = backend
209 .get_object::<Repository>(&object.to_string(), &operation_state)
210 .await
211 .unwrap();
212
213 let mut repository_backend = state.repository_backend.lock().await;
214 let branches = repository_backend
215 .repository_get_branches(&requester, object.object(), &operation)
216 .await
217 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
218 drop(repository_backend);
219
220 Ok(branches)
221 }
222 .boxed_local()
223 }
224
225 pub fn repository_file_from_id(
226 object: &Repository,
227 operation: RepositoryFileFromIdRequest,
228 state: DatabaseBackend,
229 operation_state: StackOperationState,
230 backend: Arc<GiteratedStack>,
231
232 requester: Option<AuthenticatedUser>,
233 ) -> LocalBoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> {
234 let object = object.clone();
235
236 async move {
237 let object = backend
238 .get_object::<Repository>(&object.to_string(), &operation_state)
239 .await
240 .unwrap();
241
242 let mut repository_backend = state.repository_backend.lock().await;
243 let file = repository_backend
244 .repository_file_from_id(
245 &requester,
246 object.object(),
247 &RepositoryFileFromIdRequest(operation.0),
248 )
249 .await
250 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
251 drop(repository_backend);
252
253 Ok(file)
254 }
255 .boxed_local()
256 }
257
258 pub fn repository_file_from_path(
259 object: &Repository,
260 operation: RepositoryFileFromPathRequest,
261 state: DatabaseBackend,
262 operation_state: StackOperationState,
263 backend: Arc<GiteratedStack>,
264 requester: Option<AuthenticatedUser>,
265 ) -> LocalBoxFuture<'static, Result<(RepositoryFile, String), OperationError<RepositoryError>>> {
266 let object = object.clone();
267
268 async move {
269 let object = backend
270 .get_object::<Repository>(&object.to_string(), &operation_state)
271 .await
272 .unwrap();
273
274 let mut repository_backend = state.repository_backend.lock().await;
275 let file = repository_backend
276 .repository_file_from_path(
277 &requester,
278 object.object(),
279 &RepositoryFileFromPathRequest {
280 rev: operation.rev,
281 path: operation.path,
282 },
283 )
284 .await
285 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
286 drop(repository_backend);
287
288 Ok(file)
289 }
290 .boxed_local()
291 }
292
293 pub fn repository_last_commit_of_file(
294 object: &Repository,
295 operation: RepositoryLastCommitOfFileRequest,
296 state: DatabaseBackend,
297 operation_state: StackOperationState,
298 backend: Arc<GiteratedStack>,
299 requester: Option<AuthenticatedUser>,
300 ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> {
301 let object = object.clone();
302
303 async move {
304 let object = backend
305 .get_object::<Repository>(&object.to_string(), &operation_state)
306 .await
307 .unwrap();
308
309 let mut repository_backend = state.repository_backend.lock().await;
310 let commit = repository_backend
311 .repository_last_commit_of_file(
312 &requester,
313 object.object(),
314 &RepositoryLastCommitOfFileRequest {
315 start_commit: operation.start_commit,
316 path: operation.path,
317 },
318 )
319 .await
320 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
321 drop(repository_backend);
322
323 Ok(commit)
324 }
325 .boxed_local()
326 }
327
328 pub fn repository_commit_by_id(
329 object: &Repository,
330 operation: RepositoryCommitFromIdRequest,
331 state: DatabaseBackend,
332 operation_state: StackOperationState,
333 backend: Arc<GiteratedStack>,
334 requester: Option<AuthenticatedUser>,
335 ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> {
336 let object = object.clone();
337
338 async move {
339 let object = backend
340 .get_object::<Repository>(&object.to_string(), &operation_state)
341 .await
342 .unwrap();
343
344 let mut repository_backend = state.repository_backend.lock().await;
345 let commit = repository_backend
346 .repository_commit_from_id(
347 &requester,
348 object.object(),
349 &RepositoryCommitFromIdRequest(operation.0),
350 )
351 .await
352 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
353 drop(repository_backend);
354
355 Ok(commit)
356 }
357 .boxed_local()
358 }
359
360 pub fn repository_diff(
361 object: &Repository,
362 operation: RepositoryDiffRequest,
363 state: DatabaseBackend,
364 operation_state: StackOperationState,
365 backend: Arc<GiteratedStack>,
366 requester: Option<AuthenticatedUser>,
367 ) -> LocalBoxFuture<'static, Result<RepositoryDiff, OperationError<RepositoryError>>> {
368 let object = object.clone();
369
370 async move {
371 let object = backend
372 .get_object::<Repository>(&object.to_string(), &operation_state)
373 .await
374 .unwrap();
375
376 let mut repository_backend = state.repository_backend.lock().await;
377 let diff = repository_backend
378 .repository_diff(&requester, object.object(), &operation)
379 .await
380 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
381 drop(repository_backend);
382
383 Ok(diff)
384 }
385 .boxed_local()
386 }
387
388 pub fn repository_diff_patch(
389 object: &Repository,
390 operation: RepositoryDiffPatchRequest,
391 state: DatabaseBackend,
392 operation_state: StackOperationState,
393 backend: Arc<GiteratedStack>,
394 requester: Option<AuthenticatedUser>,
395 ) -> LocalBoxFuture<'static, Result<String, OperationError<RepositoryError>>> {
396 let object = object.clone();
397
398 async move {
399 let object = backend
400 .get_object::<Repository>(&object.to_string(), &operation_state)
401 .await
402 .unwrap();
403
404 let mut repository_backend = state.repository_backend.lock().await;
405 let patch = repository_backend
406 .repository_diff_patch(&requester, object.object(), &operation)
407 .await
408 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
409 drop(repository_backend);
410
411 Ok(patch)
412 }
413 .boxed_local()
414 }
415
416 pub fn repository_commit_before(
417 object: &Repository,
418 operation: RepositoryCommitBeforeRequest,
419 state: DatabaseBackend,
420 operation_state: StackOperationState,
421 backend: Arc<GiteratedStack>,
422 requester: Option<AuthenticatedUser>,
423 ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> {
424 let object = object.clone();
425
426 async move {
427 let object = backend
428 .get_object::<Repository>(&object.to_string(), &operation_state)
429 .await
430 .unwrap();
431
432 let mut repository_backend = state.repository_backend.lock().await;
433 let file = repository_backend
434 .repository_commit_before(&requester, object.object(), &operation)
435 .await
436 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
437 drop(repository_backend);
438
439 Ok(file)
440 }
441 .boxed_local()
442 }
443
444 pub fn repository_get_value(
445 object: &Repository,
446 operation: GetValueTyped<AnyValue<Repository>>,
447 state: DatabaseBackend,
448 ) -> LocalBoxFuture<'static, Result<AnyValue<Repository>, OperationError<GetValueError>>> {
449 let object = object.clone();
450
451 async move {
452 let mut repository_backend = state.repository_backend.lock().await;
453 let value = repository_backend
454 .get_value(&object, &operation.value_name)
455 .await
456 .map_err(|e| {
457 OperationError::Internal(format!("error getting value: {}", e.to_string()))
458 })?;
459
460 Ok(value)
461 }
462 .boxed_local()
463 }
464
465 pub fn repository_get_setting(
466 object: &Repository,
467 operation: GetSetting,
468 state: DatabaseBackend,
469 ) -> LocalBoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
470 let object = object.clone();
471
472 async move {
473 let mut repository_backend = state.repository_backend.lock().await;
474 let value = repository_backend
475 .get_setting(&object, &operation.setting_name)
476 .await
477 .map_err(|e| OperationError::Internal(e.to_string()))?;
478
479 Ok(value)
480 }
481 .boxed_local()
482 }
483
484 pub fn instance_authentication_request(
485 object: &Instance,
486 operation: AuthenticationTokenRequest,
487 state: DatabaseBackend,
488 // Authorizes the request for SAME-INSTANCE
489 _authorized_instance: AuthorizedInstance,
490 ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> {
491 let object = object.clone();
492 async move {
493 let mut backend = state.user_backend.lock().await;
494
495 backend
496 .login(&object, operation)
497 .await
498 .map_err(|e| OperationError::Internal(e.to_string()))
499 }
500 .boxed_local()
501 }
502
503 pub fn instance_registration_request(
504 _object: &Instance,
505 operation: RegisterAccountRequest,
506 state: DatabaseBackend,
507 // Authorizes the request for SAME-INSTANCE
508 _authorized_instance: AuthorizedInstance,
509 ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> {
510 async move {
511 let mut backend = state.user_backend.lock().await;
512
513 backend
514 .register(operation)
515 .await
516 .map_err(|e| OperationError::Internal(e.to_string()))
517 }
518 .boxed_local()
519 }
520
521 pub fn instance_create_repository_request(
522 _object: &Instance,
523 operation: RepositoryCreateRequest,
524 state: DatabaseBackend,
525 requester: AuthenticatedUser,
526 // Authorizes the request for SAME-INSTANCE
527 _authorized_instance: AuthorizedInstance,
528 ) -> LocalBoxFuture<'static, Result<Repository, OperationError<InstanceError>>> {
529 async move {
530 let mut backend = state.repository_backend.lock().await;
531
532 backend
533 .create_repository(&requester, &operation)
534 .await
535 .map_err(|e| OperationError::Internal(e.to_string()))
536 }
537 .boxed_local()
538 }
539
540 pub fn user_get_value_display_name(
541 object: &User,
542 operation: GetValueTyped<DisplayName>,
543 state: DatabaseBackend,
544 // _requester: AuthorizedUser,
545 ) -> LocalBoxFuture<'static, Result<DisplayName, OperationError<GetValueError>>> {
546 let object = object.clone();
547
548 async move {
549 let mut backend = state.user_backend.lock().await;
550
551 let raw_value = backend
552 .get_value(&object, &operation.value_name)
553 .await
554 .map_err(|e| OperationError::Internal(e.to_string()))?;
555
556 Ok(serde_json::from_value(raw_value.into_inner())
557 .map_err(|e| OperationError::Internal(e.to_string()))?)
558 }
559 .boxed_local()
560 }
561
562 pub fn user_get_value_bio(
563 object: &User,
564 operation: GetValueTyped<Bio>,
565 state: DatabaseBackend,
566 ) -> LocalBoxFuture<'static, Result<Bio, OperationError<GetValueError>>> {
567 let object = object.clone();
568
569 async move {
570 let mut backend = state.user_backend.lock().await;
571
572 let raw_value = backend
573 .get_value(&object, &operation.value_name)
574 .await
575 .map_err(|e| OperationError::Internal(e.to_string()))?;
576
577 Ok(serde_json::from_value(raw_value.into_inner())
578 .map_err(|e| OperationError::Internal(e.to_string()))?)
579 }
580 .boxed_local()
581 }
582
583 pub fn repository_get_value_description(
584 object: &Repository,
585 operation: GetValueTyped<Description>,
586 state: DatabaseBackend,
587 ) -> LocalBoxFuture<'static, Result<Description, OperationError<GetValueError>>> {
588 let object = object.clone();
589
590 async move {
591 let mut backend = state.repository_backend.lock().await;
592
593 let raw_value = backend
594 .get_value(&object, &operation.value_name)
595 .await
596 .map_err(|e| OperationError::Internal(e.to_string()))?;
597
598 Ok(serde_json::from_value(raw_value.into_inner())
599 .map_err(|e| OperationError::Internal(e.to_string()))?)
600 }
601 .boxed_local()
602 }
603
604 pub fn repository_get_value_visibility(
605 object: &Repository,
606 operation: GetValueTyped<Visibility>,
607 state: DatabaseBackend,
608 ) -> LocalBoxFuture<'static, Result<Visibility, OperationError<GetValueError>>> {
609 let object = object.clone();
610
611 async move {
612 let mut backend = state.repository_backend.lock().await;
613
614 let raw_value = backend
615 .get_value(&object, &operation.value_name)
616 .await
617 .map_err(|e| OperationError::Internal(e.to_string()))?;
618
619 Ok(serde_json::from_value(raw_value.into_inner())
620 .map_err(|e| OperationError::Internal(e.to_string()))?)
621 }
622 .boxed_local()
623 }
624
625 pub fn repository_get_default_branch(
626 object: &Repository,
627 operation: GetValueTyped<DefaultBranch>,
628 state: DatabaseBackend,
629 ) -> LocalBoxFuture<'static, Result<DefaultBranch, OperationError<GetValueError>>> {
630 let object = object.clone();
631
632 async move {
633 let mut backend = state.repository_backend.lock().await;
634
635 let raw_value = backend
636 .get_value(&object, &operation.value_name)
637 .await
638 .map_err(|e| OperationError::Internal(e.to_string()))?;
639
640 Ok(serde_json::from_value(raw_value.into_inner())
641 .map_err(|e| OperationError::Internal(e.to_string()))?)
642 }
643 .boxed_local()
644 }
645
646 pub fn repository_get_latest_commit(
647 object: &Repository,
648 operation: GetValueTyped<LatestCommit>,
649 state: DatabaseBackend,
650 ) -> LocalBoxFuture<'static, Result<LatestCommit, OperationError<GetValueError>>> {
651 let object = object.clone();
652
653 async move {
654 let mut backend = state.repository_backend.lock().await;
655
656 let raw_value = backend
657 .get_value(&object, &operation.value_name)
658 .await
659 .map_err(|e| OperationError::Internal(e.to_string()))?;
660
661 Ok(serde_json::from_value(raw_value.into_inner())
662 .map_err(|e| OperationError::Internal(e.to_string()))?)
663 }
664 .boxed_local()
665 }
666