initial git dump

This commit is contained in:
Jonas Rabenstein 2026-02-16 02:51:10 +01:00
commit 781e25470b
47 changed files with 2361 additions and 0 deletions

View file

@ -0,0 +1 @@
pub trait Credentials: super::super::Request {}

View file

@ -0,0 +1,2 @@
pub mod login;
pub use login::Credentials;

View 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
View 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
}
}

View 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
View 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
View 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;

View 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
View 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
View 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)
}