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

ambee/giterated

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

Add `AuthorizedOperation`

Implement `AuthorizedOperation` for `RegisterAccountRequest`, `AuthenticationTokenRequest`, `RepositoryCreateRequest`, Implement `FromOperationState` for `AuthorizedUser` and `AuthorizedInstance`, depending on the operation being `AuthorizedOperation<Object>`

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨1dcec18

Showing ⁨⁨4⁩ changed files⁩ with ⁨⁨190⁩ insertions⁩ and ⁨⁨27⁩ deletions⁩

giterated-daemon/src/database_backend/handler.rs

View file
@@ -19,7 +19,7 @@ use giterated_models::{
19 19 user::{User, UserRepositoriesRequest},
20 20 value::{AnyValue, GetValue},
21 21 };
22 use giterated_stack::{AuthenticatedUser, BackendWrapper, StackOperationState};
22 use giterated_stack::{AuthenticatedUser, AuthorizedInstance, BackendWrapper, StackOperationState};
23 23
24 24 use super::DatabaseBackend;
25 25
@@ -382,6 +382,8 @@ pub fn instance_authentication_request(
382 382 object: &Instance,
383 383 operation: AuthenticationTokenRequest,
384 384 state: DatabaseBackend,
385 // Authorizes the request for SAME-INSTANCE
386 _authorized_instance: AuthorizedInstance,
385 387 ) -> BoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> {
386 388 let object = object.clone();
387 389 async move {
@@ -399,6 +401,8 @@ pub fn instance_registration_request(
399 401 _object: &Instance,
400 402 operation: RegisterAccountRequest,
401 403 state: DatabaseBackend,
404 // Authorizes the request for SAME-INSTANCE
405 _authorized_instance: AuthorizedInstance,
402 406 ) -> BoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> {
403 407 async move {
404 408 let mut backend = state.user_backend.lock().await;
@@ -416,6 +420,8 @@ pub fn instance_create_repository_request(
416 420 operation: RepositoryCreateRequest,
417 421 state: DatabaseBackend,
418 422 requester: AuthenticatedUser,
423 // Authorizes the request for SAME-INSTANCE
424 _authorized_instance: AuthorizedInstance,
419 425 ) -> BoxFuture<'static, Result<Repository, OperationError<InstanceError>>> {
420 426 async move {
421 427 let mut backend = state.repository_backend.lock().await;

giterated-daemon/src/main.rs

View file
@@ -95,6 +95,8 @@ async fn main() -> Result<(), Error> {
95 95
96 96 let operation_state = {
97 97 StackOperationState {
98 our_instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap())
99 .unwrap(),
98 100 giterated_backend: backend_wrapper,
99 101 instance: None,
100 102 user: None,

giterated-models/src/lib.rs

View file
@@ -1,3 +1,7 @@
1 use error::OperationError;
2 use object::GiteratedObject;
3 use operation::GiteratedOperation;
4
1 5 pub mod authenticated;
2 6 pub mod discovery;
3 7 pub mod error;

giterated-stack/src/lib.rs

View file
@@ -6,7 +6,9 @@ use std::{collections::HashMap, future::Future, ops::Deref, pin::Pin, str::FromS
6 6 use futures_util::FutureExt;
7 7 use giterated_models::{
8 8 error::OperationError,
9 instance::Instance,
9 instance::{
10 AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest,
11 },
10 12 object::{
11 13 AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse,
12 14 },
@@ -224,10 +226,10 @@ where
224 226 + Sync
225 227 + Clone,
226 228 O: GiteratedObject + Send + Sync,
227 D: GiteratedOperation<O> + 'static,
229 D: GiteratedOperation<O> + 'static + Send + Sync,
228 230 <D as GiteratedOperation<O>>::Failure: Send,
229 231 S: Send + Sync + Clone + 'static,
230 O1: FromOperationState,
232 O1: FromOperationState<O, D>,
231 233 {
232 234 fn operation_name(&self) -> &str {
233 235 D::operation_name()
@@ -244,7 +246,7 @@ where
244 246 state: S,
245 247 operation_state: &StackOperationState,
246 248 ) -> Result<D::Success, OperationError<D::Failure>> {
247 let o1 = O1::from_state(operation_state)
249 let o1 = O1::from_state(object, &operation, operation_state)
248 250 .await
249 251 .map_err(|e| OperationError::Internal(e.to_string()))?;
250 252 self.clone()(object, operation, state, o1).await
@@ -266,11 +268,11 @@ where
266 268 + Sync
267 269 + Clone,
268 270 O: GiteratedObject + Send + Sync,
269 D: GiteratedOperation<O> + 'static,
271 D: GiteratedOperation<O> + 'static + Send + Sync,
270 272 <D as GiteratedOperation<O>>::Failure: Send,
271 273 S: Send + Sync + Clone + 'static,
272 O1: FromOperationState,
273 O2: FromOperationState,
274 O1: FromOperationState<O, D>,
275 O2: FromOperationState<O, D>,
274 276 {
275 277 fn operation_name(&self) -> &str {
276 278 D::operation_name()
@@ -287,10 +289,10 @@ where
287 289 state: S,
288 290 operation_state: &StackOperationState,
289 291 ) -> Result<D::Success, OperationError<D::Failure>> {
290 let o1 = O1::from_state(operation_state)
292 let o1 = O1::from_state(object, &operation, operation_state)
291 293 .await
292 294 .map_err(|e| OperationError::Internal(e.to_string()))?;
293 let o2 = O2::from_state(operation_state)
295 let o2 = O2::from_state(object, &operation, operation_state)
294 296 .await
295 297 .map_err(|e| OperationError::Internal(e.to_string()))?;
296 298 self.clone()(object, operation, state, o1, o2).await
@@ -313,12 +315,12 @@ where
313 315 + Sync
314 316 + Clone,
315 317 O: GiteratedObject + Send + Sync,
316 D: GiteratedOperation<O> + 'static,
318 D: GiteratedOperation<O> + 'static + Send + Sync,
317 319 <D as GiteratedOperation<O>>::Failure: Send,
318 320 S: Send + Sync + Clone + 'static,
319 O1: FromOperationState,
320 O2: FromOperationState,
321 O3: FromOperationState,
321 O1: FromOperationState<O, D>,
322 O2: FromOperationState<O, D>,
323 O3: FromOperationState<O, D>,
322 324 {
323 325 fn operation_name(&self) -> &str {
324 326 D::operation_name()
@@ -335,13 +337,13 @@ where
335 337 state: S,
336 338 operation_state: &StackOperationState,
337 339 ) -> Result<D::Success, OperationError<D::Failure>> {
338 let o1 = O1::from_state(operation_state)
340 let o1 = O1::from_state(object, &operation, operation_state)
339 341 .await
340 342 .map_err(|e| OperationError::Internal(e.to_string()))?;
341 let o2 = O2::from_state(operation_state)
343 let o2 = O2::from_state(object, &operation, operation_state)
342 344 .await
343 345 .map_err(|e| OperationError::Internal(e.to_string()))?;
344 let o3 = O3::from_state(operation_state)
346 let o3 = O3::from_state(object, &operation, operation_state)
345 347 .await
346 348 .map_err(|e| OperationError::Internal(e.to_string()))?;
347 349 self.clone()(object, operation, state, o1, o2, o3).await
@@ -416,26 +418,42 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> {
416 418 }
417 419
418 420 #[async_trait::async_trait]
419 pub trait FromOperationState: Sized + Clone + Send {
421 pub trait FromOperationState<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync>:
422 Sized + Clone + Send
423 {
420 424 type Error: Serialize + DeserializeOwned;
421 425
422 async fn from_state(state: &StackOperationState) -> Result<Self, OperationError<Self::Error>>;
426 async fn from_state(
427 object: &O,
428 operation: &D,
429 state: &StackOperationState,
430 ) -> Result<Self, OperationError<Self::Error>>;
423 431 }
424 432
425 433 #[async_trait::async_trait]
426 impl FromOperationState for BackendWrapper {
434 impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D>
435 for BackendWrapper
436 {
427 437 type Error = ();
428 438
429 async fn from_state(state: &StackOperationState) -> Result<Self, OperationError<()>> {
439 async fn from_state(
440 _object: &O,
441 _operation: &D,
442 state: &StackOperationState,
443 ) -> Result<Self, OperationError<()>> {
430 444 Ok(state.giterated_backend.clone())
431 445 }
432 446 }
433 447
434 448 #[async_trait::async_trait]
435 impl FromOperationState for StackOperationState {
449 impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D>
450 for StackOperationState
451 {
436 452 type Error = ();
437 453
438 454 async fn from_state(
455 _object: &O,
456 _operation: &D,
439 457 state: &StackOperationState,
440 458 ) -> Result<StackOperationState, OperationError<()>> {
441 459 Ok(state.clone())
@@ -443,10 +461,14 @@ impl FromOperationState for StackOperationState {
443 461 }
444 462
445 463 #[async_trait::async_trait]
446 impl FromOperationState for AuthenticatedUser {
464 impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D>
465 for AuthenticatedUser
466 {
447 467 type Error = ();
448 468
449 469 async fn from_state(
470 _object: &O,
471 _operation: &D,
450 472 state: &StackOperationState,
451 473 ) -> Result<AuthenticatedUser, OperationError<()>> {
452 474 state
@@ -457,10 +479,14 @@ impl FromOperationState for AuthenticatedUser {
457 479 }
458 480
459 481 #[async_trait::async_trait]
460 impl FromOperationState for AuthenticatedInstance {
482 impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D>
483 for AuthenticatedInstance
484 {
461 485 type Error = ();
462 486
463 487 async fn from_state(
488 _object: &O,
489 _operation: &D,
464 490 state: &StackOperationState,
465 491 ) -> Result<AuthenticatedInstance, OperationError<()>> {
466 492 state
@@ -471,16 +497,141 @@ impl FromOperationState for AuthenticatedInstance {
471 497 }
472 498
473 499 #[async_trait::async_trait]
474 impl<T: FromOperationState> FromOperationState for Option<T> {
500 impl<
501 T: FromOperationState<O, D> + Send + Sync,
502 O: GiteratedObject + Sync,
503 D: GiteratedOperation<O> + Send + Sync,
504 > FromOperationState<O, D> for Option<T>
505 {
506 type Error = ();
507
508 async fn from_state(
509 object: &O,
510 operation: &D,
511 state: &StackOperationState,
512 ) -> Result<Option<T>, OperationError<()>> {
513 Ok(T::from_state(object, operation, state).await.ok())
514 }
515 }
516
517 #[derive(Clone)]
518 pub struct AuthorizedUser(AuthenticatedUser);
519
520 #[derive(Clone)]
521 pub struct AuthorizedInstance(AuthenticatedInstance);
522
523 #[async_trait::async_trait]
524 pub trait AuthorizedOperation<O: GiteratedObject>: GiteratedOperation<O> {
525 async fn authorize(
526 &self,
527 authorize_for: &O,
528 state: &StackOperationState,
529 ) -> Result<bool, OperationError<()>>;
530 }
531
532 #[async_trait::async_trait]
533 impl AuthorizedOperation<Instance> for RegisterAccountRequest {
534 async fn authorize(
535 &self,
536 authorize_for: &Instance,
537 state: &StackOperationState,
538 ) -> Result<bool, OperationError<()>> {
539 if state.our_instance == *authorize_for {
540 Ok(true)
541 } else {
542 Ok(false)
543 }
544 }
545 }
546
547 #[async_trait::async_trait]
548 impl AuthorizedOperation<Instance> for AuthenticationTokenRequest {
549 async fn authorize(
550 &self,
551 authorize_for: &Instance,
552 state: &StackOperationState,
553 ) -> Result<bool, OperationError<()>> {
554 if state.our_instance == *authorize_for {
555 Ok(true)
556 } else {
557 Ok(false)
558 }
559 }
560 }
561
562 #[async_trait::async_trait]
563 impl AuthorizedOperation<Instance> for RepositoryCreateRequest {
564 async fn authorize(
565 &self,
566 authorize_for: &Instance,
567 state: &StackOperationState,
568 ) -> Result<bool, OperationError<()>> {
569 if state.our_instance == *authorize_for {
570 Ok(true)
571 } else {
572 Ok(false)
573 }
574 }
575 }
576
577 #[async_trait::async_trait]
578 impl<A: AuthorizedOperation<User> + Send + Sync> FromOperationState<User, A> for AuthorizedUser {
475 579 type Error = ();
476 580
477 async fn from_state(state: &StackOperationState) -> Result<Option<T>, OperationError<()>> {
478 Ok(T::from_state(state).await.ok())
581 async fn from_state(
582 object: &User,
583 operation: &A,
584 state: &StackOperationState,
585 ) -> Result<AuthorizedUser, OperationError<()>> {
586 let authenticated = AuthenticatedUser::from_state(object, operation, state).await?;
587
588 match operation.authorize(object, state).await {
589 Ok(authorized) => {
590 assert!(authorized);
591 }
592 Err(err) => return Err(OperationError::Internal(err.to_string())),
593 };
594
595 Ok(AuthorizedUser(authenticated))
479 596 }
480 597 }
481 598
599 #[async_trait::async_trait]
600 impl<A: AuthorizedOperation<Instance> + Send + Sync> FromOperationState<Instance, A>
601 for AuthorizedInstance
602 {
603 type Error = ();
604
605 async fn from_state(
606 object: &Instance,
607 operation: &A,
608 state: &StackOperationState,
609 ) -> Result<AuthorizedInstance, OperationError<()>> {
610 let authenticated = AuthenticatedInstance::from_state(object, operation, state).await?;
611
612 match operation.authorize(object, state).await {
613 Ok(authorized) => {
614 assert!(authorized);
615 }
616 Err(err) => return Err(OperationError::Internal(err.to_string())),
617 };
618
619 Ok(AuthorizedInstance(authenticated))
620 }
621 }
622
623 // #[async_trait::async_trait> FromOperationState for Option<T> {
624 // type Error = ();
625
626 // async fn from_state(state: &StackOperationState) -> Result<Option<T>, OperationError<()>> {
627 // Ok(T::from_state(]
628 // impl<T: FromOperationStatestate).await.ok())
629 // }
630 // }
631
482 632 #[derive(Clone)]
483 633 pub struct StackOperationState {
634 pub our_instance: Instance,
484 635 pub giterated_backend: BackendWrapper,
485 636 pub instance: Option<AuthenticatedInstance>,
486 637 pub user: Option<AuthenticatedUser>,