Implement Serialize, Deserialize and TryFromMultipart for Username/Password
Enable the axum feature to use it
This commit is contained in:
parent
2d1f3a985f
commit
4eb3ac6350
|
@ -15,7 +15,13 @@ serde = { version = "1", features = [ "derive" ] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
regex = "1.9"
|
regex = "1.9"
|
||||||
url = "2.4"
|
url = "2.4"
|
||||||
|
futures-util = { version = "0.3", optional = true }
|
||||||
|
axum = { version = "0.6", optional = true }
|
||||||
|
axum_typed_multipart = { version = "0.8", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
scan-rules = "0.2"
|
scan-rules = "0.2"
|
||||||
tokio = { version = "1", features = [ "sync", "rt" ] }
|
tokio = { version = "1", features = [ "sync", "rt" ] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
axum = [ "dep:futures-util", "dep:axum", "dep:axum_typed_multipart" ]
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
use ldap3::dn_escape;
|
use ldap3::dn_escape;
|
||||||
use serde::{Serialize, Deserialize};
|
use snafu::prelude::*;
|
||||||
use snafu::OptionExt;
|
|
||||||
|
#[cfg(feature="axum")]
|
||||||
|
use axum::{
|
||||||
|
async_trait,
|
||||||
|
body::Bytes,
|
||||||
|
};
|
||||||
|
#[cfg(feature="axum")]
|
||||||
|
use axum_typed_multipart::{FieldMetadata, TryFromChunks, TypedMultipartError};
|
||||||
|
#[cfg(feature="axum")]
|
||||||
|
use futures_util::stream::Stream;
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize, Deserializer};
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
@ -14,7 +25,7 @@ fn non_empty_string(s: &str) -> Option<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)]
|
||||||
pub struct Username(String);
|
pub struct Username(String);
|
||||||
|
|
||||||
impl Username {
|
impl Username {
|
||||||
|
@ -56,7 +67,29 @@ impl std::fmt::Display for Username {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
impl<'de> Deserialize<'de> for Username {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
let s = String::deserialize(deserializer)?;
|
||||||
|
FromStr::from_str(&s).map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="axum")]
|
||||||
|
#[async_trait]
|
||||||
|
impl TryFromChunks for Username {
|
||||||
|
async fn try_from_chunks(
|
||||||
|
chunks: impl Stream<Item = Result<Bytes, TypedMultipartError>> + Send + Sync + Unpin,
|
||||||
|
metadata: FieldMetadata,
|
||||||
|
) -> Result<Self, TypedMultipartError> {
|
||||||
|
let string = String::try_from_chunks(chunks, metadata).await?;
|
||||||
|
let data = Self::from_str(&string).map_err(|e| TypedMultipartError::Other { source: e.into() })?;
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub struct Password(String);
|
pub struct Password(String);
|
||||||
|
|
||||||
impl Password {
|
impl Password {
|
||||||
|
@ -81,3 +114,25 @@ impl FromStr for Password {
|
||||||
Password::new(s)
|
Password::new(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Password {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
let s = String::deserialize(deserializer)?;
|
||||||
|
FromStr::from_str(&s).map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="axum")]
|
||||||
|
#[async_trait]
|
||||||
|
impl TryFromChunks for Password {
|
||||||
|
async fn try_from_chunks(
|
||||||
|
chunks: impl Stream<Item = Result<Bytes, TypedMultipartError>> + Send + Sync + Unpin,
|
||||||
|
metadata: FieldMetadata,
|
||||||
|
) -> Result<Self, TypedMultipartError> {
|
||||||
|
let string = String::try_from_chunks(chunks, metadata).await?;
|
||||||
|
let data = Self::from_str(&string).map_err(|e| TypedMultipartError::Other { source: e.into() })?;
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::Username;
|
use crate::Username;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SSOWatConfig {
|
pub struct SSOWatConfig {
|
||||||
domains: Vec<String>,
|
domains: Vec<String>,
|
||||||
permissions: HashMap<PermissionName, Permission>,
|
permissions: HashMap<PermissionName, Permission>,
|
||||||
|
@ -32,7 +32,7 @@ impl SSOWatConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub struct Permission {
|
pub struct Permission {
|
||||||
auth_header: bool,
|
auth_header: bool,
|
||||||
label: String,
|
label: String,
|
||||||
|
@ -43,7 +43,7 @@ pub struct Permission {
|
||||||
users: Vec<Username>,
|
users: Vec<Username>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct PermissionName {
|
pub struct PermissionName {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
name: String,
|
name: String,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user