diff --git a/giterated-daemon/src/database_backend/handler.rs b/giterated-daemon/src/database_backend/handler.rs index 799341f..f270a6f 100644 --- a/giterated-daemon/src/database_backend/handler.rs +++ b/giterated-daemon/src/database_backend/handler.rs @@ -19,7 +19,7 @@ use giterated_models::{ user::{User, UserRepositoriesRequest}, value::{AnyValue, GetValue}, }; -use giterated_stack::{AuthenticatedUser, BackendWrapper, StackOperationState}; +use giterated_stack::{AuthenticatedUser, AuthorizedInstance, BackendWrapper, StackOperationState}; use super::DatabaseBackend; @@ -382,6 +382,8 @@ pub fn instance_authentication_request( object: &Instance, operation: AuthenticationTokenRequest, state: DatabaseBackend, + // Authorizes the request for SAME-INSTANCE + _authorized_instance: AuthorizedInstance, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { @@ -399,6 +401,8 @@ pub fn instance_registration_request( _object: &Instance, operation: RegisterAccountRequest, state: DatabaseBackend, + // Authorizes the request for SAME-INSTANCE + _authorized_instance: AuthorizedInstance, ) -> BoxFuture<'static, Result>> { async move { let mut backend = state.user_backend.lock().await; @@ -416,6 +420,8 @@ pub fn instance_create_repository_request( operation: RepositoryCreateRequest, state: DatabaseBackend, requester: AuthenticatedUser, + // Authorizes the request for SAME-INSTANCE + _authorized_instance: AuthorizedInstance, ) -> BoxFuture<'static, Result>> { async move { let mut backend = state.repository_backend.lock().await; diff --git a/giterated-daemon/src/main.rs b/giterated-daemon/src/main.rs index 98e705a..6da61dc 100644 --- a/giterated-daemon/src/main.rs +++ b/giterated-daemon/src/main.rs @@ -95,6 +95,8 @@ async fn main() -> Result<(), Error> { let operation_state = { StackOperationState { + our_instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()) + .unwrap(), giterated_backend: backend_wrapper, instance: None, user: None, diff --git a/giterated-models/src/lib.rs b/giterated-models/src/lib.rs index 57e5bc4..0c0c39d 100644 --- a/giterated-models/src/lib.rs +++ b/giterated-models/src/lib.rs @@ -1,3 +1,7 @@ +use error::OperationError; +use object::GiteratedObject; +use operation::GiteratedOperation; + pub mod authenticated; pub mod discovery; pub mod error; diff --git a/giterated-stack/src/lib.rs b/giterated-stack/src/lib.rs index 03b61fa..686f411 100644 --- a/giterated-stack/src/lib.rs +++ b/giterated-stack/src/lib.rs @@ -6,7 +6,9 @@ use std::{collections::HashMap, future::Future, ops::Deref, pin::Pin, str::FromS use futures_util::FutureExt; use giterated_models::{ error::OperationError, - instance::Instance, + instance::{ + AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest, + }, object::{ AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse, }, @@ -224,10 +226,10 @@ where + Sync + Clone, O: GiteratedObject + Send + Sync, - D: GiteratedOperation + 'static, + D: GiteratedOperation + 'static + Send + Sync, >::Failure: Send, S: Send + Sync + Clone + 'static, - O1: FromOperationState, + O1: FromOperationState, { fn operation_name(&self) -> &str { D::operation_name() @@ -244,7 +246,7 @@ where state: S, operation_state: &StackOperationState, ) -> Result> { - let o1 = O1::from_state(operation_state) + let o1 = O1::from_state(object, &operation, operation_state) .await .map_err(|e| OperationError::Internal(e.to_string()))?; self.clone()(object, operation, state, o1).await @@ -266,11 +268,11 @@ where + Sync + Clone, O: GiteratedObject + Send + Sync, - D: GiteratedOperation + 'static, + D: GiteratedOperation + 'static + Send + Sync, >::Failure: Send, S: Send + Sync + Clone + 'static, - O1: FromOperationState, - O2: FromOperationState, + O1: FromOperationState, + O2: FromOperationState, { fn operation_name(&self) -> &str { D::operation_name() @@ -287,10 +289,10 @@ where state: S, operation_state: &StackOperationState, ) -> Result> { - let o1 = O1::from_state(operation_state) + let o1 = O1::from_state(object, &operation, operation_state) .await .map_err(|e| OperationError::Internal(e.to_string()))?; - let o2 = O2::from_state(operation_state) + let o2 = O2::from_state(object, &operation, operation_state) .await .map_err(|e| OperationError::Internal(e.to_string()))?; self.clone()(object, operation, state, o1, o2).await @@ -313,12 +315,12 @@ where + Sync + Clone, O: GiteratedObject + Send + Sync, - D: GiteratedOperation + 'static, + D: GiteratedOperation + 'static + Send + Sync, >::Failure: Send, S: Send + Sync + Clone + 'static, - O1: FromOperationState, - O2: FromOperationState, - O3: FromOperationState, + O1: FromOperationState, + O2: FromOperationState, + O3: FromOperationState, { fn operation_name(&self) -> &str { D::operation_name() @@ -335,13 +337,13 @@ where state: S, operation_state: &StackOperationState, ) -> Result> { - let o1 = O1::from_state(operation_state) + let o1 = O1::from_state(object, &operation, operation_state) .await .map_err(|e| OperationError::Internal(e.to_string()))?; - let o2 = O2::from_state(operation_state) + let o2 = O2::from_state(object, &operation, operation_state) .await .map_err(|e| OperationError::Internal(e.to_string()))?; - let o3 = O3::from_state(operation_state) + let o3 = O3::from_state(object, &operation, operation_state) .await .map_err(|e| OperationError::Internal(e.to_string()))?; self.clone()(object, operation, state, o1, o2, o3).await @@ -416,26 +418,42 @@ impl OperationWrapper { } #[async_trait::async_trait] -pub trait FromOperationState: Sized + Clone + Send { +pub trait FromOperationState + Send + Sync>: + Sized + Clone + Send +{ type Error: Serialize + DeserializeOwned; - async fn from_state(state: &StackOperationState) -> Result>; + async fn from_state( + object: &O, + operation: &D, + state: &StackOperationState, + ) -> Result>; } #[async_trait::async_trait] -impl FromOperationState for BackendWrapper { +impl + Send + Sync> FromOperationState + for BackendWrapper +{ type Error = (); - async fn from_state(state: &StackOperationState) -> Result> { + async fn from_state( + _object: &O, + _operation: &D, + state: &StackOperationState, + ) -> Result> { Ok(state.giterated_backend.clone()) } } #[async_trait::async_trait] -impl FromOperationState for StackOperationState { +impl + Send + Sync> FromOperationState + for StackOperationState +{ type Error = (); async fn from_state( + _object: &O, + _operation: &D, state: &StackOperationState, ) -> Result> { Ok(state.clone()) @@ -443,10 +461,14 @@ impl FromOperationState for StackOperationState { } #[async_trait::async_trait] -impl FromOperationState for AuthenticatedUser { +impl + Send + Sync> FromOperationState + for AuthenticatedUser +{ type Error = (); async fn from_state( + _object: &O, + _operation: &D, state: &StackOperationState, ) -> Result> { state @@ -457,10 +479,14 @@ impl FromOperationState for AuthenticatedUser { } #[async_trait::async_trait] -impl FromOperationState for AuthenticatedInstance { +impl + Send + Sync> FromOperationState + for AuthenticatedInstance +{ type Error = (); async fn from_state( + _object: &O, + _operation: &D, state: &StackOperationState, ) -> Result> { state @@ -471,16 +497,141 @@ impl FromOperationState for AuthenticatedInstance { } #[async_trait::async_trait] -impl FromOperationState for Option { +impl< + T: FromOperationState + Send + Sync, + O: GiteratedObject + Sync, + D: GiteratedOperation + Send + Sync, + > FromOperationState for Option +{ + type Error = (); + + async fn from_state( + object: &O, + operation: &D, + state: &StackOperationState, + ) -> Result, OperationError<()>> { + 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] +pub trait AuthorizedOperation: GiteratedOperation { + async fn authorize( + &self, + authorize_for: &O, + state: &StackOperationState, + ) -> Result>; +} + +#[async_trait::async_trait] +impl AuthorizedOperation for RegisterAccountRequest { + 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] +impl AuthorizedOperation for AuthenticationTokenRequest { + 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] +impl AuthorizedOperation for RepositoryCreateRequest { + 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] +impl + Send + Sync> FromOperationState for AuthorizedUser { type Error = (); - async fn from_state(state: &StackOperationState) -> Result, OperationError<()>> { - Ok(T::from_state(state).await.ok()) + async fn from_state( + object: &User, + operation: &A, + state: &StackOperationState, + ) -> Result> { + let authenticated = AuthenticatedUser::from_state(object, operation, state).await?; + + match operation.authorize(object, state).await { + Ok(authorized) => { + assert!(authorized); + } + Err(err) => return Err(OperationError::Internal(err.to_string())), + }; + + Ok(AuthorizedUser(authenticated)) } } +#[async_trait::async_trait] +impl + Send + Sync> FromOperationState + for AuthorizedInstance +{ + type Error = (); + + async fn from_state( + object: &Instance, + operation: &A, + state: &StackOperationState, + ) -> Result> { + let authenticated = AuthenticatedInstance::from_state(object, operation, state).await?; + + match operation.authorize(object, state).await { + Ok(authorized) => { + assert!(authorized); + } + Err(err) => return Err(OperationError::Internal(err.to_string())), + }; + + 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 user: Option,