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⁩ - ⁨17046⁩ 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,
13 RepositoryCommitBeforeRequest, RepositoryDiff, RepositoryDiffPatchRequest,
14 RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest,
15 RepositoryFileFromPathRequest, RepositoryFileInspectRequest, RepositoryInfoRequest,
16 RepositorySummary, RepositoryView, Visibility,
17 },
18 settings::{AnySetting, GetSetting, GetSettingError},
19 user::{Bio, DisplayName, User, UserRepositoriesRequest},
20 value::{AnyValue, GetValueTyped},
21 };
22 use giterated_stack::{AuthenticatedUser, AuthorizedInstance, GiteratedStack, StackOperationState};
23
24 use super::DatabaseBackend;
25
26 pub fn user_get_repositories(
27 object: &User,
28 _operation: UserRepositoriesRequest,
29 state: DatabaseBackend,
30 _operation_state: StackOperationState,
31 requester: Option<AuthenticatedUser>,
32 ) -> LocalBoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> {
33 let object = object.clone();
34
35 async move {
36 let mut user_backend = state.user_backend.lock().await;
37 let repositories_response = user_backend
38 .repositories_for_user(&requester, &object)
39 .await
40 .map_err(|e| OperationError::Internal(e.to_string()))?;
41 drop(user_backend);
42 let mut repositories_backend = state.repository_backend.lock().await;
43
44 let mut repositories = vec![];
45
46 for repository in repositories_response {
47 if repositories_backend
48 .exists(&requester, &repository.repository)
49 .await
50 .map_err(|e| OperationError::Internal(e.to_string()))?
51 {
52 repositories.push(repository);
53 }
54 }
55
56 Ok(repositories)
57 }
58 .boxed_local()
59 }
60
61 pub fn user_get_value(
62 object: &User,
63 operation: GetValueTyped<AnyValue<User>>,
64 state: DatabaseBackend,
65 ) -> LocalBoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> {
66 let object = object.clone();
67
68 async move {
69 let mut user_backend = state.user_backend.lock().await;
70 let value = user_backend
71 .get_value(&object, &operation.value_name)
72 .await
73 .map_err(|e| OperationError::Internal(e.to_string()))?;
74
75 Ok(value)
76 }
77 .boxed_local()
78 }
79
80 pub fn user_get_setting(
81 object: &User,
82 operation: GetSetting,
83 state: DatabaseBackend,
84 ) -> LocalBoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
85 let object = object.clone();
86
87 async move {
88 let mut user_backend = state.user_backend.lock().await;
89 let value = user_backend
90 .get_setting(&object, &operation.setting_name)
91 .await
92 .map_err(|e| OperationError::Internal(e.to_string()))?;
93
94 Ok(value)
95 }
96 .boxed_local()
97 }
98
99 pub fn repository_info(
100 object: &Repository,
101 operation: RepositoryInfoRequest,
102 state: DatabaseBackend,
103 operation_state: StackOperationState,
104 backend: Arc<GiteratedStack>,
105 requester: Option<AuthenticatedUser>,
106 ) -> LocalBoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> {
107 let object = object.clone();
108
109 async move {
110 let mut object = backend
111 .get_object::<Repository>(&object.to_string(), &operation_state)
112 .await
113 .unwrap();
114 let mut repository_backend = state.repository_backend.lock().await;
115 let tree = repository_backend
116 .repository_file_inspect(
117 &requester,
118 object.object(),
119 &RepositoryFileInspectRequest {
120 extra_metadata: operation.extra_metadata,
121 path: operation.path,
122 rev: operation.rev.clone(),
123 },
124 )
125 .await
126 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
127 drop(repository_backend);
128
129 let info = RepositoryView {
130 name: object.object().name.clone(),
131 owner: object.object().owner.clone(),
132 description: object.get::<Description>(&operation_state).await.ok(),
133 visibility: object
134 .get::<Visibility>(&operation_state)
135 .await
136 .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?,
137 default_branch: object
138 .get::<DefaultBranch>(&operation_state)
139 .await
140 .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?,
141 // 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.
142 latest_commit: object.get::<LatestCommit>(&operation_state).await.ok(),
143 tree_rev: operation.rev,
144 tree,
145 };
146
147 Ok(info)
148 }
149 .boxed_local()
150 }
151
152 pub fn repository_file_from_id(
153 object: &Repository,
154 operation: RepositoryFileFromIdRequest,
155 state: DatabaseBackend,
156 operation_state: StackOperationState,
157 backend: Arc<GiteratedStack>,
158
159 requester: Option<AuthenticatedUser>,
160 ) -> LocalBoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> {
161 let object = object.clone();
162
163 async move {
164 let object = backend
165 .get_object::<Repository>(&object.to_string(), &operation_state)
166 .await
167 .unwrap();
168
169 let mut repository_backend = state.repository_backend.lock().await;
170 let file = repository_backend
171 .repository_file_from_id(
172 &requester,
173 object.object(),
174 &RepositoryFileFromIdRequest(operation.0),
175 )
176 .await
177 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
178 drop(repository_backend);
179
180 Ok(file)
181 }
182 .boxed_local()
183 }
184
185 pub fn repository_file_from_path(
186 object: &Repository,
187 operation: RepositoryFileFromPathRequest,
188 state: DatabaseBackend,
189 operation_state: StackOperationState,
190 backend: Arc<GiteratedStack>,
191 requester: Option<AuthenticatedUser>,
192 ) -> LocalBoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> {
193 let object = object.clone();
194
195 async move {
196 let object = backend
197 .get_object::<Repository>(&object.to_string(), &operation_state)
198 .await
199 .unwrap();
200
201 let mut repository_backend = state.repository_backend.lock().await;
202 let file = repository_backend
203 .repository_file_from_path(
204 &requester,
205 object.object(),
206 &RepositoryFileFromPathRequest {
207 rev: operation.rev,
208 path: operation.path,
209 },
210 )
211 .await
212 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
213 drop(repository_backend);
214
215 Ok(file)
216 }
217 .boxed_local()
218 }
219
220 pub fn repository_diff(
221 object: &Repository,
222 operation: RepositoryDiffRequest,
223 state: DatabaseBackend,
224 operation_state: StackOperationState,
225 backend: Arc<GiteratedStack>,
226 requester: Option<AuthenticatedUser>,
227 ) -> LocalBoxFuture<'static, Result<RepositoryDiff, OperationError<RepositoryError>>> {
228 let object = object.clone();
229
230 async move {
231 let object = backend
232 .get_object::<Repository>(&object.to_string(), &operation_state)
233 .await
234 .unwrap();
235
236 let mut repository_backend = state.repository_backend.lock().await;
237 let diff = repository_backend
238 .repository_diff(&requester, object.object(), &operation)
239 .await
240 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
241 drop(repository_backend);
242
243 Ok(diff)
244 }
245 .boxed_local()
246 }
247
248 pub fn repository_diff_patch(
249 object: &Repository,
250 operation: RepositoryDiffPatchRequest,
251 state: DatabaseBackend,
252 operation_state: StackOperationState,
253 backend: Arc<GiteratedStack>,
254 requester: Option<AuthenticatedUser>,
255 ) -> LocalBoxFuture<'static, Result<String, OperationError<RepositoryError>>> {
256 let object = object.clone();
257
258 async move {
259 let object = backend
260 .get_object::<Repository>(&object.to_string(), &operation_state)
261 .await
262 .unwrap();
263
264 let mut repository_backend = state.repository_backend.lock().await;
265 let patch = repository_backend
266 .repository_diff_patch(&requester, object.object(), &operation)
267 .await
268 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
269 drop(repository_backend);
270
271 Ok(patch)
272 }
273 .boxed_local()
274 }
275
276 pub fn repository_commit_before(
277 object: &Repository,
278 operation: RepositoryCommitBeforeRequest,
279 state: DatabaseBackend,
280 operation_state: StackOperationState,
281 backend: Arc<GiteratedStack>,
282 requester: Option<AuthenticatedUser>,
283 ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> {
284 let object = object.clone();
285
286 async move {
287 let object = backend
288 .get_object::<Repository>(&object.to_string(), &operation_state)
289 .await
290 .unwrap();
291
292 let mut repository_backend = state.repository_backend.lock().await;
293 let file = repository_backend
294 .repository_commit_before(&requester, object.object(), &operation)
295 .await
296 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
297 drop(repository_backend);
298
299 Ok(file)
300 }
301 .boxed_local()
302 }
303
304 pub fn repository_get_value(
305 object: &Repository,
306 operation: GetValueTyped<AnyValue<Repository>>,
307 state: DatabaseBackend,
308 ) -> LocalBoxFuture<'static, Result<AnyValue<Repository>, OperationError<GetValueError>>> {
309 let object = object.clone();
310
311 async move {
312 let mut repository_backend = state.repository_backend.lock().await;
313 let value = repository_backend
314 .get_value(&object, &operation.value_name)
315 .await
316 .map_err(|e| {
317 OperationError::Internal(format!("error getting value: {}", e.to_string()))
318 })?;
319
320 Ok(value)
321 }
322 .boxed_local()
323 }
324
325 pub fn repository_get_setting(
326 object: &Repository,
327 operation: GetSetting,
328 state: DatabaseBackend,
329 ) -> LocalBoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
330 let object = object.clone();
331
332 async move {
333 let mut repository_backend = state.repository_backend.lock().await;
334 let value = repository_backend
335 .get_setting(&object, &operation.setting_name)
336 .await
337 .map_err(|e| OperationError::Internal(e.to_string()))?;
338
339 Ok(value)
340 }
341 .boxed_local()
342 }
343
344 pub fn instance_authentication_request(
345 object: &Instance,
346 operation: AuthenticationTokenRequest,
347 state: DatabaseBackend,
348 // Authorizes the request for SAME-INSTANCE
349 _authorized_instance: AuthorizedInstance,
350 ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> {
351 let object = object.clone();
352 async move {
353 let mut backend = state.user_backend.lock().await;
354
355 backend
356 .login(&object, operation)
357 .await
358 .map_err(|e| OperationError::Internal(e.to_string()))
359 }
360 .boxed_local()
361 }
362
363 pub fn instance_registration_request(
364 _object: &Instance,
365 operation: RegisterAccountRequest,
366 state: DatabaseBackend,
367 // Authorizes the request for SAME-INSTANCE
368 _authorized_instance: AuthorizedInstance,
369 ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> {
370 async move {
371 let mut backend = state.user_backend.lock().await;
372
373 backend
374 .register(operation)
375 .await
376 .map_err(|e| OperationError::Internal(e.to_string()))
377 }
378 .boxed_local()
379 }
380
381 pub fn instance_create_repository_request(
382 _object: &Instance,
383 operation: RepositoryCreateRequest,
384 state: DatabaseBackend,
385 requester: AuthenticatedUser,
386 // Authorizes the request for SAME-INSTANCE
387 _authorized_instance: AuthorizedInstance,
388 ) -> LocalBoxFuture<'static, Result<Repository, OperationError<InstanceError>>> {
389 async move {
390 let mut backend = state.repository_backend.lock().await;
391
392 backend
393 .create_repository(&requester, &operation)
394 .await
395 .map_err(|e| OperationError::Internal(e.to_string()))
396 }
397 .boxed_local()
398 }
399
400 pub fn user_get_value_display_name(
401 object: &User,
402 operation: GetValueTyped<DisplayName>,
403 state: DatabaseBackend,
404 // _requester: AuthorizedUser,
405 ) -> LocalBoxFuture<'static, Result<DisplayName, OperationError<GetValueError>>> {
406 let object = object.clone();
407
408 async move {
409 let mut backend = state.user_backend.lock().await;
410
411 let raw_value = backend
412 .get_value(&object, &operation.value_name)
413 .await
414 .map_err(|e| OperationError::Internal(e.to_string()))?;
415
416 Ok(serde_json::from_value(raw_value.into_inner())
417 .map_err(|e| OperationError::Internal(e.to_string()))?)
418 }
419 .boxed_local()
420 }
421
422 pub fn user_get_value_bio(
423 object: &User,
424 operation: GetValueTyped<Bio>,
425 state: DatabaseBackend,
426 ) -> LocalBoxFuture<'static, Result<Bio, OperationError<GetValueError>>> {
427 let object = object.clone();
428
429 async move {
430 let mut backend = state.user_backend.lock().await;
431
432 let raw_value = backend
433 .get_value(&object, &operation.value_name)
434 .await
435 .map_err(|e| OperationError::Internal(e.to_string()))?;
436
437 Ok(serde_json::from_value(raw_value.into_inner())
438 .map_err(|e| OperationError::Internal(e.to_string()))?)
439 }
440 .boxed_local()
441 }
442
443 pub fn repository_get_value_description(
444 object: &Repository,
445 operation: GetValueTyped<Description>,
446 state: DatabaseBackend,
447 ) -> LocalBoxFuture<'static, Result<Description, OperationError<GetValueError>>> {
448 let object = object.clone();
449
450 async move {
451 let mut backend = state.repository_backend.lock().await;
452
453 let raw_value = backend
454 .get_value(&object, &operation.value_name)
455 .await
456 .map_err(|e| OperationError::Internal(e.to_string()))?;
457
458 Ok(serde_json::from_value(raw_value.into_inner())
459 .map_err(|e| OperationError::Internal(e.to_string()))?)
460 }
461 .boxed_local()
462 }
463
464 pub fn repository_get_value_visibility(
465 object: &Repository,
466 operation: GetValueTyped<Visibility>,
467 state: DatabaseBackend,
468 ) -> LocalBoxFuture<'static, Result<Visibility, OperationError<GetValueError>>> {
469 let object = object.clone();
470
471 async move {
472 let mut backend = state.repository_backend.lock().await;
473
474 let raw_value = backend
475 .get_value(&object, &operation.value_name)
476 .await
477 .map_err(|e| OperationError::Internal(e.to_string()))?;
478
479 Ok(serde_json::from_value(raw_value.into_inner())
480 .map_err(|e| OperationError::Internal(e.to_string()))?)
481 }
482 .boxed_local()
483 }
484
485 pub fn repository_get_default_branch(
486 object: &Repository,
487 operation: GetValueTyped<DefaultBranch>,
488 state: DatabaseBackend,
489 ) -> LocalBoxFuture<'static, Result<DefaultBranch, OperationError<GetValueError>>> {
490 let object = object.clone();
491
492 async move {
493 let mut backend = state.repository_backend.lock().await;
494
495 let raw_value = backend
496 .get_value(&object, &operation.value_name)
497 .await
498 .map_err(|e| OperationError::Internal(e.to_string()))?;
499
500 Ok(serde_json::from_value(raw_value.into_inner())
501 .map_err(|e| OperationError::Internal(e.to_string()))?)
502 }
503 .boxed_local()
504 }
505
506 pub fn repository_get_latest_commit(
507 object: &Repository,
508 operation: GetValueTyped<LatestCommit>,
509 state: DatabaseBackend,
510 ) -> LocalBoxFuture<'static, Result<LatestCommit, OperationError<GetValueError>>> {
511 let object = object.clone();
512
513 async move {
514 let mut backend = state.repository_backend.lock().await;
515
516 let raw_value = backend
517 .get_value(&object, &operation.value_name)
518 .await
519 .map_err(|e| OperationError::Internal(e.to_string()))?;
520
521 Ok(serde_json::from_value(raw_value.into_inner())
522 .map_err(|e| OperationError::Internal(e.to_string()))?)
523 }
524 .boxed_local()
525 }
526