mod handler; mod meta; pub use handler::{GiteratedStack, GiteratedStackState, *}; pub use meta::*; pub mod state; pub mod update; use std::{any::Any, convert::Infallible, future::Future, ops::Deref, pin::Pin, sync::Arc}; use core::fmt::Debug; use futures_util::FutureExt; use giterated_models::{ error::{ExtractorError, IntoInternalError, OperationError, UnauthorizedError}, instance::{ AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest, }, object::GiteratedObject, object_backend::ObjectBackend, operation::GiteratedOperation, repository::{AccessList, Repository}, settings::{GetSetting, SetSetting}, user::User, value::GetValue, }; #[derive(Clone, Debug, Hash, Eq, PartialEq)] struct ObjectOperationPair { pub object_name: String, pub operation_name: String, } #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct ObjectValuePair { pub object_kind: String, pub value_kind: String, } #[async_trait::async_trait(?Send)] pub trait GiteratedOperationHandler< L, O: GiteratedObject, D: GiteratedOperation, S: Send + Sync + Clone, > { fn operation_name(&self) -> &str; fn object_name(&self) -> &str; async fn handle( &self, object: &O, operation: D, state: S, operation_state: &StackOperationState, ) -> Result>; } #[async_trait::async_trait(?Send)] impl GiteratedOperationHandler<(), O, D, S> for F where F: FnMut( &O, D, S, ) -> Pin>>>> + Send + Sync + Clone, O: GiteratedObject + Send + Sync, D: GiteratedOperation + 'static, >::Failure: Send, S: Send + Sync + Clone + 'static, { fn operation_name(&self) -> &str { D::operation_name() } fn object_name(&self) -> &str { O::object_name() } async fn handle( &self, object: &O, operation: D, state: S, _operation_state: &StackOperationState, ) -> Result> { self.clone()(object, operation, state).await } } #[async_trait::async_trait(?Send)] impl GiteratedOperationHandler<(O1,), O, D, S> for F where F: FnMut( &O, D, S, O1, ) -> Pin>>>> + Send + Sync + Clone, O: GiteratedObject + Send + Sync, D: GiteratedOperation + 'static + Send + Sync, >::Failure: Send, S: Send + Sync + Clone + 'static, O1: FromOperationState, ExtractorError<>::Error>: Into, { fn operation_name(&self) -> &str { D::operation_name() } fn object_name(&self) -> &str { O::object_name() } async fn handle( &self, object: &O, operation: D, state: S, operation_state: &StackOperationState, ) -> Result> { let o1 = O1::from_state(object, &operation, operation_state) .await .as_internal_error()?; self.clone()(object, operation, state, o1).await } } #[async_trait::async_trait(?Send)] impl GiteratedOperationHandler<(O1, O2), O, D, S> for F where F: FnMut( &O, D, S, O1, O2, ) -> Pin>>>> + Send + Sync + Clone, O: GiteratedObject + Send + Sync, D: GiteratedOperation + 'static + Send + Sync, >::Failure: Send, S: Send + Sync + Clone + 'static, O1: FromOperationState, ExtractorError<>::Error>: Into, O2: FromOperationState, ExtractorError<>::Error>: Into, { fn operation_name(&self) -> &str { D::operation_name() } fn object_name(&self) -> &str { O::object_name() } async fn handle( &self, object: &O, operation: D, state: S, operation_state: &StackOperationState, ) -> Result> { let o1 = O1::from_state(object, &operation, operation_state) .await .as_internal_error()?; let o2 = O2::from_state(object, &operation, operation_state) .await .as_internal_error()?; self.clone()(object, operation, state, o1, o2).await } } #[async_trait::async_trait(?Send)] impl GiteratedOperationHandler<(O1, O2, O3), O, D, S> for F where F: FnMut( &O, D, S, O1, O2, O3, ) -> Pin>>>> + Send + Sync + Clone, O: GiteratedObject + Send + Sync, D: GiteratedOperation + 'static + Send + Sync, >::Failure: Send, S: Send + Sync + Clone + 'static, O1: FromOperationState, ExtractorError<>::Error>: Into, O2: FromOperationState, ExtractorError<>::Error>: Into, O3: FromOperationState, ExtractorError<>::Error>: Into, { fn operation_name(&self) -> &str { D::operation_name() } fn object_name(&self) -> &str { O::object_name() } async fn handle( &self, object: &O, operation: D, state: S, operation_state: &StackOperationState, ) -> Result> { let o1 = O1::from_state(object, &operation, operation_state) .await .as_internal_error()?; let o2 = O2::from_state(object, &operation, operation_state) .await .as_internal_error()?; let o3 = O3::from_state(object, &operation, operation_state) .await .as_internal_error()?; self.clone()(object, operation, state, o1, o2, o3).await } } pub struct OperationWrapper { func: Box< dyn Fn( &(dyn Any + Send + Sync), &(dyn Any + Send + Sync), &(dyn Any + Send + Sync), StackOperationState, ) -> Pin< Box< dyn Future< Output = Result< Box, OperationError>, >, >, >, > + Send + Sync, >, state: Box, } impl OperationWrapper { pub fn new< A, O: GiteratedObject + Send + Sync + 'static, D: GiteratedOperation + 'static + Clone, F: GiteratedOperationHandler + 'static + Send + Sync + Clone, S: GiteratedStackState + 'static, >( handler: F, state: S, ) -> Self where D::Failure: Send + Sync, D::Success: Send + Sync, { Self { func: Box::new(move |object, operation, state, operation_state| { let handler = handler.clone(); let state = state.downcast_ref::().unwrap().clone(); let object: &O = object.downcast_ref().unwrap(); let operation: &D = operation.downcast_ref().unwrap(); let object = object.clone(); let operation = operation.clone(); async move { let result = handler .handle(&object, operation, state, &operation_state) .await; result .map(|success| Box::new(success) as _) .map_err(|err| match err { OperationError::Operation(err) => { OperationError::Operation(Box::new(err) as _) } OperationError::Internal(internal) => { OperationError::Internal(internal) } OperationError::Unhandled => OperationError::Unhandled, }) } .boxed_local() }), state: Box::new(state), } } async fn handle( &self, object: &Box, operation: &Box, operation_state: &StackOperationState, ) -> Result, OperationError>> { (self.func)( (*object).as_ref(), (*operation).as_ref(), self.state.as_ref(), operation_state.clone(), ) .await } } #[async_trait::async_trait(?Send)] pub trait FromOperationState>: Sized + Clone { type Error: Into; async fn from_state( object: &O, operation: &D, state: &StackOperationState, ) -> Result>; } #[async_trait::async_trait(?Send)] impl> FromOperationState for Arc { type Error = Infallible; async fn from_state( _object: &O, _operation: &D, state: &StackOperationState, ) -> Result> { Ok(state.runtime.clone()) } } #[async_trait::async_trait(?Send)] impl> FromOperationState for StackOperationState { type Error = Infallible; async fn from_state( _object: &O, _operation: &D, state: &StackOperationState, ) -> Result> { Ok(state.clone()) } } #[derive(Debug, thiserror::Error)] #[error("missing value")] pub struct MissingValue; #[async_trait::async_trait(?Send)] impl + Send + Sync> FromOperationState for AuthenticatedUser { type Error = MissingValue; async fn from_state( _object: &O, _operation: &D, state: &StackOperationState, ) -> Result> { state .user .clone() .ok_or_else(|| ExtractorError(MissingValue)) } } #[async_trait::async_trait(?Send)] impl + Send + Sync> FromOperationState for AuthenticatedInstance { type Error = MissingValue; async fn from_state( _object: &O, _operation: &D, state: &StackOperationState, ) -> Result> { state .instance .clone() .ok_or_else(|| ExtractorError(MissingValue)) } } #[async_trait::async_trait(?Send)] impl< T: FromOperationState + Send + Sync, O: GiteratedObject + Sync, D: GiteratedOperation + Send + Sync, > FromOperationState for Option { type Error = Infallible; async fn from_state( object: &O, operation: &D, state: &StackOperationState, ) -> Result, ExtractorError> { Ok(T::from_state(object, operation, state).await.ok()) } } #[derive(Clone)] pub struct AuthorizedUser(AuthenticatedUser); #[derive(Clone)] pub struct AuthorizedInstance(AuthenticatedInstance); #[async_trait::async_trait(?Send)] pub trait AuthorizedOperation: GiteratedOperation { type Error: Into; async fn authorize( &self, authorize_for: &O, state: &StackOperationState, ) -> Result>; } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for GetValue { type Error = anyhow::Error; async fn authorize( &self, authorize_for: &O, operation_state: &StackOperationState, ) -> Result> { Ok(operation_state .runtime .get_object::(&authorize_for.to_string(), operation_state) .await .is_ok()) } } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for SetSetting { type Error = MissingValue; async fn authorize( &self, authorize_for: &User, operation_state: &StackOperationState, ) -> Result> { let authenticated_user = operation_state.user.as_ref().ok_or_else(|| MissingValue)?; Ok(authorize_for == authenticated_user.deref()) } } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for GetSetting { type Error = MissingValue; async fn authorize( &self, authorize_for: &User, operation_state: &StackOperationState, ) -> Result> { let authenticated_user = operation_state.user.as_ref().ok_or_else(|| MissingValue)?; Ok(authorize_for == authenticated_user.deref()) } } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for SetSetting { type Error = anyhow::Error; async fn authorize( &self, authorize_for: &Repository, operation_state: &StackOperationState, ) -> Result> { let authenticated_user = operation_state .user .as_ref() .ok_or_else(|| anyhow::Error::from(MissingValue))?; let mut object = operation_state .runtime .get_object::(&authorize_for.to_string(), operation_state) .await .map_err(|err| anyhow::Error::from(err))?; let access_list = object .get_setting::(operation_state) .await .map_err(|err| anyhow::Error::from(err))?; if access_list .0 .iter() .find(|user| *user == authenticated_user.deref()) .is_some() { Ok(true) } else { Ok(false) } } } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for GetSetting { type Error = anyhow::Error; async fn authorize( &self, authorize_for: &Repository, operation_state: &StackOperationState, ) -> Result> { let authenticated_user = operation_state .user .as_ref() .ok_or_else(|| anyhow::Error::from(MissingValue))?; let mut object = operation_state .runtime .get_object::(&authorize_for.to_string(), operation_state) .await .map_err(|err| anyhow::Error::from(err))?; let access_list = object .get_setting::(operation_state) .await .map_err(|err| anyhow::Error::from(err))?; if access_list .0 .iter() .find(|user| *user == authenticated_user.deref()) .is_some() { Ok(true) } else { Ok(false) } } } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for RegisterAccountRequest { type Error = Infallible; async fn authorize( &self, authorize_for: &Instance, state: &StackOperationState, ) -> Result> { if state.our_instance == *authorize_for { Ok(true) } else { Ok(false) } } } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for AuthenticationTokenRequest { type Error = Infallible; async fn authorize( &self, authorize_for: &Instance, state: &StackOperationState, ) -> Result> { if state.our_instance == *authorize_for { Ok(true) } else { Ok(false) } } } #[async_trait::async_trait(?Send)] impl AuthorizedOperation for RepositoryCreateRequest { type Error = Infallible; async fn authorize( &self, authorize_for: &Instance, state: &StackOperationState, ) -> Result> { if state.our_instance == *authorize_for { Ok(true) } else { Ok(false) } } } #[async_trait::async_trait(?Send)] impl + Send + Sync> FromOperationState for AuthorizedUser { type Error = UnauthorizedError; async fn from_state( object: &User, operation: &A, state: &StackOperationState, ) -> Result> { // TODO let authenticated = AuthenticatedUser::from_state(object, operation, state) .await .map_err(|_| ExtractorError(UnauthorizedError))?; match operation.authorize(object, state).await { Ok(authorized) => { assert!(authorized); } Err(_err) => return Err(ExtractorError(UnauthorizedError)), }; Ok(AuthorizedUser(authenticated)) } } #[async_trait::async_trait(?Send)] impl + Send + Sync> FromOperationState for AuthorizedInstance { type Error = UnauthorizedError; async fn from_state( object: &Instance, operation: &A, state: &StackOperationState, ) -> Result> { //TODO let authenticated = AuthenticatedInstance::from_state(object, operation, state) .await .map_err(|_| ExtractorError(UnauthorizedError))?; match operation.authorize(object, state).await { Ok(authorized) => { assert!(authorized); } Err(_err) => return Err(ExtractorError(UnauthorizedError)), }; Ok(AuthorizedInstance(authenticated)) } } // #[async_trait::async_trait> FromOperationState for Option { // type Error = (); // async fn from_state(state: &StackOperationState) -> Result, OperationError<()>> { // Ok(T::from_state(] // impl, pub instance: Option, pub user: Option, } #[derive(Clone, Debug)] pub struct AuthenticatedInstance(Instance); impl AuthenticatedInstance { pub fn new(instance: Instance) -> Self { AuthenticatedInstance(instance) } } impl Deref for AuthenticatedInstance { type Target = Instance; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Clone, Debug)] pub struct AuthenticatedUser(User); impl AuthenticatedUser { pub fn new(user: User) -> Self { AuthenticatedUser(user) } } impl Deref for AuthenticatedUser { type Target = User; fn deref(&self) -> &Self::Target { &self.0 } }