From 4eb3ac63506e7ff0213ffafd402cce11775913f6 Mon Sep 17 00:00:00 2001 From: selfhoster1312 Date: Tue, 22 Aug 2023 16:51:52 +0200 Subject: [PATCH] Implement Serialize, Deserialize and TryFromMultipart for Username/Password Enable the axum feature to use it --- yunohost-api/Cargo.toml | 6 +++ yunohost-api/src/credentials.rs | 63 ++++++++++++++++++++++++-- yunohost-api/src/permissions/ssowat.rs | 6 +-- 3 files changed, 68 insertions(+), 7 deletions(-) diff --git a/yunohost-api/Cargo.toml b/yunohost-api/Cargo.toml index b55ac5c..1ec44de 100644 --- a/yunohost-api/Cargo.toml +++ b/yunohost-api/Cargo.toml @@ -15,7 +15,13 @@ serde = { version = "1", features = [ "derive" ] } serde_json = "1" regex = "1.9" 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] scan-rules = "0.2" tokio = { version = "1", features = [ "sync", "rt" ] } + +[features] +axum = [ "dep:futures-util", "dep:axum", "dep:axum_typed_multipart" ] diff --git a/yunohost-api/src/credentials.rs b/yunohost-api/src/credentials.rs index 8921e26..ccb04a0 100644 --- a/yunohost-api/src/credentials.rs +++ b/yunohost-api/src/credentials.rs @@ -1,6 +1,17 @@ use ldap3::dn_escape; -use serde::{Serialize, Deserialize}; -use snafu::OptionExt; +use snafu::prelude::*; + +#[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; @@ -14,7 +25,7 @@ fn non_empty_string(s: &str) -> Option { } } -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)] pub struct Username(String); impl Username { @@ -56,7 +67,29 @@ impl std::fmt::Display for Username { } } -#[derive(Clone, Debug)] +impl<'de> Deserialize<'de> for Username { + fn deserialize(deserializer: D) -> Result + 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> + Send + Sync + Unpin, + metadata: FieldMetadata, + ) -> Result { + 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); impl Password { @@ -81,3 +114,25 @@ impl FromStr for Password { Password::new(s) } } + +impl<'de> Deserialize<'de> for Password { + fn deserialize(deserializer: D) -> Result + 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> + Send + Sync + Unpin, + metadata: FieldMetadata, + ) -> Result { + 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) + } +} diff --git a/yunohost-api/src/permissions/ssowat.rs b/yunohost-api/src/permissions/ssowat.rs index e34bc0f..e295838 100644 --- a/yunohost-api/src/permissions/ssowat.rs +++ b/yunohost-api/src/permissions/ssowat.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use crate::Username; -#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct SSOWatConfig { domains: Vec, permissions: HashMap, @@ -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 { auth_header: bool, label: String, @@ -43,7 +43,7 @@ pub struct Permission { users: Vec, } -#[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 { #[serde(flatten)] name: String,