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