use crate::primitives::authorizer::Authorizer;
use crate::primitives::issuer::Issuer;
use crate::primitives::registrar::Registrar;
use crate::primitives::scope::Scope;
use crate::endpoint::{AccessTokenFlow, AuthorizationFlow, ResourceFlow, RefreshFlow, ClientCredentialsFlow};
use crate::endpoint::{Endpoint, Extension, OAuthError, PreGrant, Template, Scopes};
use crate::endpoint::{OwnerConsent, OwnerSolicitor, Solicitation};
use crate::endpoint::WebRequest;
use std::marker::PhantomData;
#[derive(Debug)]
pub enum Error<W: WebRequest> {
Web(W::Error),
OAuth(OAuthError),
}
pub struct Generic<R, A, I, S = Vacant, C = Vacant, L = Vacant> {
pub registrar: R,
pub authorizer: A,
pub issuer: I,
pub solicitor: S,
pub scopes: C,
pub response: L,
}
pub struct ErrorInto<E, Error>(E, PhantomData<Error>);
impl<E, Error> ErrorInto<E, Error> {
pub fn new(endpoint: E) -> Self {
ErrorInto(endpoint, PhantomData)
}
}
pub struct Vacant;
pub struct FnSolicitor<F>(pub F);
pub struct ApprovedGrant {
pub owner: String,
pub grant: PreGrant,
}
pub trait OptRegistrar {
fn opt_ref(&self) -> Option<&dyn Registrar>;
}
pub trait OptAuthorizer {
fn opt_mut(&mut self) -> Option<&mut dyn Authorizer>;
}
pub trait OptIssuer {
fn opt_mut(&mut self) -> Option<&mut dyn Issuer>;
}
pub trait ResponseCreator<W: WebRequest> {
fn create(&mut self, request: &mut W, kind: Template) -> W::Response;
}
type Authorization<'a, W> = Generic<
&'a (dyn Registrar + 'a),
&'a mut (dyn Authorizer + 'a),
Vacant,
&'a mut (dyn OwnerSolicitor<W> + 'a),
Vacant,
Vacant,
>;
type AccessToken<'a> = Generic<
&'a (dyn Registrar + 'a),
&'a mut (dyn Authorizer + 'a),
&'a mut (dyn Issuer + 'a),
Vacant,
Vacant,
Vacant,
>;
type ClientCredentials<'a, W> = Generic<
&'a (dyn Registrar + 'a),
Vacant,
&'a mut (dyn Issuer + 'a),
&'a mut (dyn OwnerSolicitor<W> + 'a),
Vacant,
Vacant,
>;
type Refresh<'a> =
Generic<&'a (dyn Registrar + 'a), Vacant, &'a mut (dyn Issuer + 'a), Vacant, Vacant, Vacant>;
type Resource<'a> = Generic<Vacant, Vacant, &'a mut (dyn Issuer + 'a), Vacant, &'a [Scope], Vacant>;
pub fn authorization_flow<'a, W>(
registrar: &'a dyn Registrar, authorizer: &'a mut dyn Authorizer,
solicitor: &'a mut dyn OwnerSolicitor<W>,
) -> AuthorizationFlow<Authorization<'a, W>, W>
where
W: WebRequest,
W::Response: Default,
{
let flow = AuthorizationFlow::prepare(Generic {
registrar,
authorizer,
issuer: Vacant,
solicitor,
scopes: Vacant,
response: Vacant,
});
match flow {
Err(_) => unreachable!(),
Ok(flow) => flow,
}
}
pub fn access_token_flow<'a, W>(
registrar: &'a dyn Registrar, authorizer: &'a mut dyn Authorizer, issuer: &'a mut dyn Issuer,
) -> AccessTokenFlow<AccessToken<'a>, W>
where
W: WebRequest,
W::Response: Default,
{
let flow = AccessTokenFlow::prepare(Generic {
registrar,
authorizer,
issuer,
solicitor: Vacant,
scopes: Vacant,
response: Vacant,
});
match flow {
Err(_) => unreachable!(),
Ok(flow) => flow,
}
}
pub fn client_credentials_flow<'a, W>(
registrar: &'a dyn Registrar, issuer: &'a mut dyn Issuer, solicitor: &'a mut dyn OwnerSolicitor<W>,
) -> ClientCredentialsFlow<ClientCredentials<'a, W>, W>
where
W: WebRequest,
W::Response: Default,
{
let flow = ClientCredentialsFlow::prepare(Generic {
registrar,
authorizer: Vacant,
issuer,
solicitor,
scopes: Vacant,
response: Vacant,
});
match flow {
Err(_) => unreachable!(),
Ok(flow) => flow,
}
}
pub fn resource_flow<'a, W>(
issuer: &'a mut dyn Issuer, scopes: &'a [Scope],
) -> ResourceFlow<Resource<'a>, W>
where
W: WebRequest,
W::Response: Default,
{
let flow = ResourceFlow::prepare(Generic {
registrar: Vacant,
authorizer: Vacant,
issuer,
solicitor: Vacant,
scopes,
response: Vacant,
});
match flow {
Err(_) => unreachable!(),
Ok(flow) => flow,
}
}
pub fn refresh_flow<'a, W>(
registrar: &'a dyn Registrar, issuer: &'a mut dyn Issuer,
) -> RefreshFlow<Refresh<'a>, W>
where
W: WebRequest,
W::Response: Default,
{
let flow = RefreshFlow::prepare(Generic {
registrar,
authorizer: Vacant,
issuer,
solicitor: Vacant,
scopes: Vacant,
response: Vacant,
});
match flow {
Err(_) => unreachable!(),
Ok(flow) => flow,
}
}
impl<R, A, I, O, C, L> Generic<R, A, I, O, C, L> {
pub fn with_solicitor<N>(self, new_solicitor: N) -> Generic<R, A, I, N, C, L> {
Generic {
registrar: self.registrar,
authorizer: self.authorizer,
issuer: self.issuer,
solicitor: new_solicitor,
scopes: self.scopes,
response: self.response,
}
}
pub fn with_scopes<S>(self, new_scopes: S) -> Generic<R, A, I, O, S, L> {
Generic {
registrar: self.registrar,
authorizer: self.authorizer,
issuer: self.issuer,
solicitor: self.solicitor,
scopes: new_scopes,
response: self.response,
}
}
pub fn authorization_flow<W: WebRequest>(self) -> AuthorizationFlow<Self, W>
where
Self: Endpoint<W>,
R: Registrar,
A: Authorizer,
{
match AuthorizationFlow::prepare(self) {
Ok(flow) => flow,
Err(_) => unreachable!(),
}
}
pub fn access_token_flow<W: WebRequest>(self) -> AccessTokenFlow<Self, W>
where
Self: Endpoint<W>,
R: Registrar,
A: Authorizer,
I: Issuer,
{
match AccessTokenFlow::prepare(self) {
Ok(flow) => flow,
Err(_) => unreachable!(),
}
}
pub fn refresh_flow<W: WebRequest>(self) -> RefreshFlow<Self, W>
where
Self: Endpoint<W>,
R: Registrar,
I: Issuer,
{
match RefreshFlow::prepare(self) {
Ok(flow) => flow,
Err(_) => unreachable!(),
}
}
pub fn resource_flow<W: WebRequest>(self) -> ResourceFlow<Self, W>
where
Self: Endpoint<W>,
I: Issuer,
{
match ResourceFlow::prepare(self) {
Ok(flow) => flow,
Err(_) => unreachable!(),
}
}
pub fn assert<W: WebRequest>(self) -> Self
where
Self: Endpoint<W>,
{
self
}
}
impl<W: WebRequest> Error<W> {
pub fn pack<P>(self) -> P
where
OAuthError: Into<P>,
W::Error: Into<P>,
{
match self {
Error::Web(err) => err.into(),
Error::OAuth(oauth) => oauth.into(),
}
}
}
impl<E, Error, W> Endpoint<W> for ErrorInto<E, Error>
where
E: Endpoint<W>,
E::Error: Into<Error>,
W: WebRequest,
{
type Error = Error;
fn registrar(&self) -> Option<&dyn Registrar> {
self.0.registrar()
}
fn authorizer_mut(&mut self) -> Option<&mut dyn Authorizer> {
self.0.authorizer_mut()
}
fn issuer_mut(&mut self) -> Option<&mut dyn Issuer> {
self.0.issuer_mut()
}
fn owner_solicitor(&mut self) -> Option<&mut dyn OwnerSolicitor<W>> {
self.0.owner_solicitor()
}
fn scopes(&mut self) -> Option<&mut dyn Scopes<W>> {
self.0.scopes()
}
fn response(&mut self, request: &mut W, kind: Template) -> Result<W::Response, Self::Error> {
self.0.response(request, kind).map_err(Into::into)
}
fn error(&mut self, err: OAuthError) -> Self::Error {
self.0.error(err).into()
}
fn web_error(&mut self, err: W::Error) -> Self::Error {
self.0.web_error(err).into()
}
fn extension(&mut self) -> Option<&mut dyn Extension> {
self.0.extension()
}
}
impl<W, R, A, I, O, C, L> Endpoint<W> for Generic<R, A, I, O, C, L>
where
W: WebRequest,
R: OptRegistrar,
A: OptAuthorizer,
I: OptIssuer,
O: OwnerSolicitor<W>,
C: Scopes<W>,
L: ResponseCreator<W>,
{
type Error = Error<W>;
fn registrar(&self) -> Option<&dyn Registrar> {
self.registrar.opt_ref()
}
fn authorizer_mut(&mut self) -> Option<&mut dyn Authorizer> {
self.authorizer.opt_mut()
}
fn issuer_mut(&mut self) -> Option<&mut dyn Issuer> {
self.issuer.opt_mut()
}
fn owner_solicitor(&mut self) -> Option<&mut dyn OwnerSolicitor<W>> {
Some(&mut self.solicitor)
}
fn scopes(&mut self) -> Option<&mut dyn Scopes<W>> {
Some(&mut self.scopes)
}
fn response(&mut self, request: &mut W, kind: Template) -> Result<W::Response, Self::Error> {
Ok(self.response.create(request, kind))
}
fn error(&mut self, err: OAuthError) -> Error<W> {
Error::OAuth(err)
}
fn web_error(&mut self, err: W::Error) -> Error<W> {
Error::Web(err)
}
}
impl<T: Registrar> OptRegistrar for T {
fn opt_ref(&self) -> Option<&dyn Registrar> {
Some(self)
}
}
impl<T: Authorizer> OptAuthorizer for T {
fn opt_mut(&mut self) -> Option<&mut dyn Authorizer> {
Some(self)
}
}
impl<T: Issuer> OptIssuer for T {
fn opt_mut(&mut self) -> Option<&mut dyn Issuer> {
Some(self)
}
}
impl OptRegistrar for Vacant {
fn opt_ref(&self) -> Option<&dyn Registrar> {
Option::None
}
}
impl OptAuthorizer for Vacant {
fn opt_mut(&mut self) -> Option<&mut dyn Authorizer> {
Option::None
}
}
impl OptIssuer for Vacant {
fn opt_mut(&mut self) -> Option<&mut dyn Issuer> {
Option::None
}
}
impl<W: WebRequest> OwnerSolicitor<W> for Vacant {
fn check_consent(&mut self, _: &mut W, _: Solicitation) -> OwnerConsent<W::Response> {
OwnerConsent::Denied
}
}
impl<W: WebRequest> Scopes<W> for Vacant {
fn scopes(&mut self, _: &mut W) -> &[Scope] {
const NO_SCOPES: [Scope; 0] = [];
&NO_SCOPES
}
}
impl<W, F> OwnerSolicitor<W> for FnSolicitor<F>
where
W: WebRequest,
F: FnMut(&mut W, Solicitation) -> OwnerConsent<W::Response>,
{
fn check_consent(
&mut self, request: &mut W, solicitation: Solicitation,
) -> OwnerConsent<W::Response> {
(self.0)(request, solicitation)
}
}
impl<W: WebRequest> OwnerSolicitor<W> for ApprovedGrant {
fn check_consent(&mut self, _: &mut W, solicitation: Solicitation) -> OwnerConsent<W::Response> {
if &self.grant == solicitation.pre_grant() {
OwnerConsent::Authorized(self.owner.clone())
} else {
OwnerConsent::Denied
}
}
}
impl<W: WebRequest> ResponseCreator<W> for Vacant
where
W::Response: Default,
{
fn create(&mut self, _: &mut W, _: Template) -> W::Response {
Default::default()
}
}
impl<W: WebRequest, F> ResponseCreator<W> for F
where
F: FnMut() -> W::Response,
{
fn create(&mut self, _: &mut W, _: Template) -> W::Response {
self()
}
}