initial git dump
This commit is contained in:
commit
781e25470b
47 changed files with 2361 additions and 0 deletions
1
api/src/traits/authentication/login.rs
Normal file
1
api/src/traits/authentication/login.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub trait Credentials: super::super::Request {}
|
||||
2
api/src/traits/authentication/mod.rs
Normal file
2
api/src/traits/authentication/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod login;
|
||||
pub use login::Credentials;
|
||||
11
api/src/traits/authorization.rs
Normal file
11
api/src/traits/authorization.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
pub trait Authorization: private::Seal {}
|
||||
|
||||
mod private {
|
||||
use crate::authorization::{False, True};
|
||||
pub trait Seal {}
|
||||
|
||||
impl Seal for True {}
|
||||
impl Seal for False {}
|
||||
}
|
||||
|
||||
impl<T: private::Seal> Authorization for T {}
|
||||
80
api/src/traits/client.rs
Normal file
80
api/src/traits/client.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use super::{Authorization, Endpoint, Request, Schema, endpoint};
|
||||
use crate::{authorization, authentication, error};
|
||||
use async_trait::async_trait;
|
||||
|
||||
pub trait Client: Public + Private {}
|
||||
|
||||
impl<C: Public + Private> Client for C {}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Handler<E: Endpoint<R, A>, R: Request, A: Authorization> {
|
||||
type Error: std::error::Error;
|
||||
|
||||
async fn execute(&self, endpoint: &E, request: &R) -> Result<E::Schema, Self::Error>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Authenticator: Public {
|
||||
type Private: Private;
|
||||
|
||||
fn with_tokens(&self, tokens: authentication::Tokens) -> Self::Private;
|
||||
|
||||
async fn authenticate<E, R>(&self, endpoint: &E, request: &R) -> Result<Self::Private, error::api::Public<<Self as Public>::Error, <E::Schema as Schema<R>>::Error>>
|
||||
where
|
||||
E: endpoint::Public<R, Schema=authentication::Tokens> + Sync,
|
||||
R: Request + Sync,
|
||||
{
|
||||
let tokens = self.execute(endpoint, request).await?;
|
||||
Ok(self.with_tokens(tokens))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Public {
|
||||
type Error: std::error::Error + Send;
|
||||
|
||||
async fn execute<E, R>(
|
||||
&self,
|
||||
endpoint: &E,
|
||||
request: &R,
|
||||
) -> Result<E::Schema, error::api::Public<Self::Error, <E::Schema as Schema<R>>::Error>>
|
||||
where
|
||||
E: endpoint::Public<R> + Sync,
|
||||
R: Request + Sync;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<P: Public + Sync, E: endpoint::Public<R> + Sync, R: Request + Sync>
|
||||
Handler<E, R, authorization::False> for P
|
||||
{
|
||||
type Error = error::api::Public<P::Error, <E::Schema as Schema<R>>::Error>;
|
||||
|
||||
async fn execute(&self, endpoint: &E, request: &R) -> Result<E::Schema, Self::Error> {
|
||||
self.execute(endpoint, request).await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Private {
|
||||
type Error: std::error::Error + Send;
|
||||
|
||||
async fn execute<E, R>(
|
||||
&self,
|
||||
endpoint: &E,
|
||||
request: &R,
|
||||
) -> Result<E::Schema, error::api::Private<Self::Error, <E::Schema as Schema<R>>::Error>>
|
||||
where
|
||||
E: endpoint::Private<R> + Sync,
|
||||
R: Request + Sync;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<P: Private + Sync, E: endpoint::Private<R> + Sync, R: Request + Sync>
|
||||
Handler<E, R, authorization::True> for P
|
||||
{
|
||||
type Error = error::api::Private<P::Error, <E::Schema as Schema<R>>::Error>;
|
||||
|
||||
async fn execute(&self, endpoint: &E, request: &R) -> Result<E::Schema, Self::Error> {
|
||||
self.execute(endpoint, request).await
|
||||
}
|
||||
}
|
||||
53
api/src/traits/endpoint.rs
Normal file
53
api/src/traits/endpoint.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use super::{Authorization, Request, Schema};
|
||||
use crate::{Method, authorization};
|
||||
|
||||
pub trait Endpoint<R: Request, A: Authorization>: private::Seal<R, A> {
|
||||
const METHOD: Method;
|
||||
type Schema: Schema<R>;
|
||||
|
||||
fn path(&self, request: &R) -> &str;
|
||||
}
|
||||
|
||||
/// A Endpoint with required authorization
|
||||
pub trait Private<R: Request> {
|
||||
const METHOD: Method;
|
||||
type Schema: Schema<R>;
|
||||
|
||||
fn path(&self, request: &R) -> &str;
|
||||
}
|
||||
|
||||
impl<T: Private<R>, R: Request> Endpoint<R, authorization::True> for T {
|
||||
const METHOD: Method = T::METHOD;
|
||||
type Schema = T::Schema;
|
||||
|
||||
fn path(&self, request: &R) -> &str {
|
||||
self.path(request)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Endpoint without required authorization
|
||||
pub trait Public<R: Request> {
|
||||
const METHOD: Method;
|
||||
type Schema: Schema<R>;
|
||||
|
||||
fn path(&self, request: &R) -> &str;
|
||||
}
|
||||
|
||||
impl<T: Public<R>, R: Request> Endpoint<R, authorization::False> for T {
|
||||
const METHOD: Method = T::METHOD;
|
||||
type Schema = T::Schema;
|
||||
|
||||
fn path(&self, request: &R) -> &str {
|
||||
self.path(request)
|
||||
}
|
||||
}
|
||||
|
||||
mod private {
|
||||
use super::*;
|
||||
|
||||
/// Seal the Endpoint dependency
|
||||
pub trait Seal<R: Request, A: Authorization> {}
|
||||
|
||||
impl<R: Request, P: Private<R>> Seal<R, authorization::True> for P {}
|
||||
impl<R: Request, P: Public<R>> Seal<R, authorization::False> for P {}
|
||||
}
|
||||
22
api/src/traits/id.rs
Normal file
22
api/src/traits/id.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use super::{
|
||||
client::Handler,
|
||||
Schema,
|
||||
Endpoint,
|
||||
};
|
||||
use crate::{
|
||||
Id,
|
||||
authorization,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait Marker: Schema<Id<Self>> + Endpoint<Id<Self>, authorization::True, Schema=Self> + std::fmt::Debug {
|
||||
async fn resolve<H: Handler<Self, Id<Self>, authorization::True> + Sync>(&self, id: &Id<Self>, handler: &H) -> Result<Self, H::Error>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T: Schema<Id<T>> + Endpoint<Id<T>, authorization::True, Schema=T> + Sync + std::fmt::Debug> Marker for T {
|
||||
async fn resolve<H: Handler<Self, Id<Self>, authorization::True> + Sync>(&self, id: &Id<Self>, handler: &H) -> Result<Self, H::Error> {
|
||||
handler.execute(&self, id).await
|
||||
}
|
||||
}
|
||||
17
api/src/traits/mod.rs
Normal file
17
api/src/traits/mod.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
pub mod authentication;
|
||||
pub mod authorization;
|
||||
pub mod client;
|
||||
pub mod endpoint;
|
||||
pub mod id;
|
||||
pub mod request;
|
||||
pub mod schema;
|
||||
|
||||
pub use authentication::Credentials;
|
||||
pub use authorization::Authorization;
|
||||
pub use client::Client;
|
||||
pub use endpoint::Endpoint;
|
||||
pub use request::Request;
|
||||
pub use schema::Schema;
|
||||
|
||||
//#[cfg(test)]
|
||||
//mod test;
|
||||
5
api/src/traits/request.rs
Normal file
5
api/src/traits/request.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
use serde::Serialize;
|
||||
|
||||
pub trait Request: Serialize + std::fmt::Debug {}
|
||||
|
||||
impl<T: Serialize + std::fmt::Debug> Request for T {}
|
||||
17
api/src/traits/schema.rs
Normal file
17
api/src/traits/schema.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use super::Request;
|
||||
use bytes::Bytes;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
pub trait Schema<R: Request>: std::fmt::Debug + Send + Sized {
|
||||
type Error: std::error::Error + Send;
|
||||
|
||||
fn deserialize(request: &R, response: &Bytes) -> Result<Self, Self::Error>;
|
||||
}
|
||||
|
||||
impl<T: DeserializeOwned + Send + std::fmt::Debug, R: Request> Schema<R> for T {
|
||||
type Error = serde_json::Error;
|
||||
|
||||
fn deserialize(_: &R, response: &Bytes) -> Result<Self, Self::Error> {
|
||||
serde_json::from_slice(&response)
|
||||
}
|
||||
}
|
||||
53
api/src/traits/test.rs
Normal file
53
api/src/traits/test.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
struct Private;
|
||||
struct Endpoint;
|
||||
#[derive(serde::Serialize)]
|
||||
struct Request;
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Schema;
|
||||
|
||||
#[async_trait]
|
||||
impl super::client::Private for Private {
|
||||
type Error = error::Private;
|
||||
|
||||
async fn execute<E, R>(&self, _: &E, _: &R) -> Result<E::Schema, error::api::Private<Self::Error, <E::Schema as Schema<R>>::Error>>
|
||||
where
|
||||
E: super::endpoint::Private<R>,
|
||||
R: super::Request + Sync,
|
||||
{
|
||||
Err(error::Private::Unauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
impl super::endpoint::Private<Request> for Endpoint {
|
||||
const METHOD: reqwest::Method = reqwest::Method::GET;
|
||||
type Schema = Schema;
|
||||
|
||||
fn path(&self, _: &Request) -> &str {
|
||||
"/core/v1/endpoint/private"
|
||||
}
|
||||
}
|
||||
|
||||
mod error {
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Private {
|
||||
#[error("unauthorized")]
|
||||
Unauthorized,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn private_endpoint() {
|
||||
use super::client::Private;
|
||||
let client = Private;
|
||||
let request = Request;
|
||||
let endpoint = Endpoint;
|
||||
let result = match client.execute(&endpoint, &request).await {
|
||||
Err(error::Private::Unauthorized) => false,
|
||||
_ => true,
|
||||
};
|
||||
assert_eq!(result, true)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue