1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Move templates to their own crate

This commit is contained in:
Quentin Gliech
2021-10-18 17:40:25 +02:00
parent cf8793da27
commit 026bc47c27
33 changed files with 319 additions and 156 deletions

View File

@ -0,0 +1,117 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{collections::HashMap, fmt::Debug, hash::Hash};
use serde::{ser::SerializeMap, Serialize};
pub trait HtmlError: Debug + Send + Sync + 'static {
fn html_display(&self) -> String;
}
pub trait WrapFormError<FieldType> {
fn on_form(self) -> ErroredForm<FieldType>;
fn on_field(self, field: FieldType) -> ErroredForm<FieldType>;
}
impl<E, FieldType> WrapFormError<FieldType> for E
where
E: HtmlError,
{
fn on_form(self) -> ErroredForm<FieldType> {
let mut f = ErroredForm::new();
f.form.push(FormError {
error: Box::new(self),
});
f
}
fn on_field(self, field: FieldType) -> ErroredForm<FieldType> {
let mut f = ErroredForm::new();
f.fields.push(FieldError {
field,
error: Box::new(self),
});
f
}
}
#[derive(Debug)]
struct FormError {
error: Box<dyn HtmlError>,
}
impl Serialize for FormError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.error.html_display())
}
}
#[derive(Debug)]
struct FieldError<FieldType> {
field: FieldType,
error: Box<dyn HtmlError>,
}
#[derive(Debug)]
pub struct ErroredForm<FieldType> {
form: Vec<FormError>,
fields: Vec<FieldError<FieldType>>,
}
impl<T> Default for ErroredForm<T> {
fn default() -> Self {
Self {
form: Vec::new(),
fields: Vec::new(),
}
}
}
impl<T> ErroredForm<T> {
#[must_use]
pub fn new() -> Self {
Self {
form: Vec::new(),
fields: Vec::new(),
}
}
}
impl<FieldType: Copy + Serialize + Hash + Eq> Serialize for ErroredForm<FieldType> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(Some(2))?;
let has_errors = !self.form.is_empty() || !self.fields.is_empty();
map.serialize_entry("has_errors", &has_errors)?;
map.serialize_entry("form_errors", &self.form)?;
let fields: HashMap<FieldType, Vec<String>> =
self.fields.iter().fold(HashMap::new(), |mut map, err| {
map.entry(err.field)
.or_default()
.push(err.error.html_display());
map
});
map.serialize_entry("fields_errors", &fields)?;
map.end()
}
}

View File

@ -16,6 +16,10 @@ use chrono::{DateTime, Duration, Utc};
use oauth2_types::{pkce::CodeChallengeMethod, scope::Scope};
use serde::Serialize;
pub mod errors;
pub trait StorageBackendMarker: StorageBackend {}
pub trait StorageBackend {
type UserData: Clone + std::fmt::Debug + PartialEq;
type AuthenticationData: Clone + std::fmt::Debug + PartialEq;
@ -26,7 +30,18 @@ pub trait StorageBackend {
type AccessTokenData: Clone + std::fmt::Debug + PartialEq;
}
impl StorageBackend for () {
type AccessTokenData = ();
type AuthenticationData = ();
type AuthorizationCodeData = ();
type BrowserSessionData = ();
type ClientData = ();
type SessionData = ();
type UserData = ();
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct User<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::UserData,
@ -47,14 +62,35 @@ where
}
}
impl<S: StorageBackendMarker> From<User<S>> for User<()> {
fn from(u: User<S>) -> Self {
User {
data: (),
username: u.username,
sub: u.sub,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct Authentication<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::AuthenticationData,
pub created_at: DateTime<Utc>,
}
impl<S: StorageBackendMarker> From<Authentication<S>> for Authentication<()> {
fn from(a: Authentication<S>) -> Self {
Authentication {
data: (),
created_at: a.created_at,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct BrowserSession<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::BrowserSessionData,
@ -63,6 +99,17 @@ pub struct BrowserSession<T: StorageBackend> {
pub last_authentication: Option<Authentication<T>>,
}
impl<S: StorageBackendMarker> From<BrowserSession<S>> for BrowserSession<()> {
fn from(s: BrowserSession<S>) -> Self {
BrowserSession {
data: (),
user: s.user.into(),
created_at: s.created_at,
last_authentication: s.last_authentication.map(Into::into),
}
}
}
impl<T: StorageBackend> BrowserSession<T>
where
T::BrowserSessionData: Default,
@ -82,13 +129,24 @@ where
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct Client<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::ClientData,
pub client_id: String,
}
impl<S: StorageBackendMarker> From<Client<S>> for Client<()> {
fn from(c: Client<S>) -> Self {
Client {
data: (),
client_id: c.client_id,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct Session<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::SessionData,
@ -97,6 +155,17 @@ pub struct Session<T: StorageBackend> {
pub scope: Scope,
}
impl<S: StorageBackendMarker> From<Session<S>> for Session<()> {
fn from(s: Session<S>) -> Self {
Session {
data: (),
browser_session: s.browser_session.map(Into::into),
client: s.client.into(),
scope: s.scope,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Pkce {
challenge_method: CodeChallengeMethod,
@ -117,6 +186,7 @@ impl Pkce {
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct AuthorizationCode<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::AuthorizationCodeData,
@ -124,6 +194,16 @@ pub struct AuthorizationCode<T: StorageBackend> {
pub pkce: Pkce,
}
impl<S: StorageBackendMarker> From<AuthorizationCode<S>> for AuthorizationCode<()> {
fn from(c: AuthorizationCode<S>) -> Self {
AuthorizationCode {
data: (),
code: c.code,
pkce: c.pkce,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AccessToken<T: StorageBackend> {
pub data: T::AccessTokenData,
@ -132,3 +212,15 @@ pub struct AccessToken<T: StorageBackend> {
pub expires_after: Duration,
pub created_at: DateTime<Utc>,
}
impl<S: StorageBackendMarker> From<AccessToken<S>> for AccessToken<()> {
fn from(t: AccessToken<S>) -> Self {
AccessToken {
data: (),
jti: t.jti,
token: t.token,
expires_after: t.expires_after,
created_at: t.created_at,
}
}
}