From db26ebe057e883d1dadf8f5037b679719ef554aa Mon Sep 17 00:00:00 2001 From: Alexander Shishenko Date: Sun, 8 Dec 2024 04:16:59 +0300 Subject: [PATCH] Remove long credential format --- notifico-core/src/credentials/env.rs | 3 +- notifico-core/src/credentials/mod.rs | 32 ++++++++------- notifico-core/src/simpletransport.rs | 4 ++ notificox/src/main.rs | 7 ++-- transports/notifico-gotify/src/credentials.rs | 19 +-------- transports/notifico-pushover/src/lib.rs | 14 +------ transports/notifico-slack/src/credentials.rs | 14 +------ transports/notifico-smpp/src/credentials.rs | 29 ++++--------- transports/notifico-smtp/src/credentials.rs | 41 +++++++------------ transports/notifico-telegram/src/lib.rs | 14 +------ .../notifico-whatsapp/src/credentials.rs | 35 +++++----------- 11 files changed, 66 insertions(+), 146 deletions(-) diff --git a/notifico-core/src/credentials/env.rs b/notifico-core/src/credentials/env.rs index b222832..aa08a5f 100644 --- a/notifico-core/src/credentials/env.rs +++ b/notifico-core/src/credentials/env.rs @@ -3,6 +3,7 @@ use crate::error::EngineError; use async_trait::async_trait; use regex::Regex; use std::collections::HashMap; +use std::str::FromStr; use tracing::info; use uuid::Uuid; @@ -29,7 +30,7 @@ impl EnvCredentialStorage { .get(1) .map_or_else(Uuid::nil, |m| Uuid::parse_str(m.as_str()).unwrap()); let name = captures.get(2).unwrap().as_str(); - let credential = Credential::Short(value); + let credential = Credential::from_str(&value).unwrap(); storage.insert( CredentialKey { diff --git a/notifico-core/src/credentials/mod.rs b/notifico-core/src/credentials/mod.rs index 1da8e07..21cab0d 100644 --- a/notifico-core/src/credentials/mod.rs +++ b/notifico-core/src/credentials/mod.rs @@ -4,7 +4,7 @@ pub mod memory; use crate::error::EngineError; use async_trait::async_trait; use serde::{Deserialize, Serialize}; -use serde_json::Value; +use std::str::FromStr; use uuid::Uuid; #[derive(Serialize, Deserialize, Debug, Clone)] @@ -15,18 +15,20 @@ pub enum CredentialSelector { /// Generic credential with type information. #[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(untagged)] -pub enum Credential { - Long { r#type: String, value: Value }, - Short(String), +pub struct Credential { + pub transport: String, + pub value: String, } -impl Credential { - pub fn transport(&self) -> &str { - match self { - Credential::Long { r#type, .. } => r#type, - Credential::Short(url) => url.split(":").next().unwrap(), - } +impl FromStr for Credential { + type Err = EngineError; + + fn from_str(s: &str) -> Result { + let (transport, value) = s + .split_once(':') + .ok_or(EngineError::InvalidCredentialFormat)?; + let (transport, value) = (transport.to_owned(), value.to_owned()); + Ok(Self { transport, value }) } } @@ -55,8 +57,10 @@ impl dyn CredentialStorage { where T: TypedCredential, { - self.get_credential(project, &selector) - .await - .and_then(|c| c.try_into()) + let credential = self.get_credential(project, &selector).await?; + if credential.transport != T::TRANSPORT_NAME { + return Err(EngineError::InvalidCredentialFormat); + } + credential.try_into() } } diff --git a/notifico-core/src/simpletransport.rs b/notifico-core/src/simpletransport.rs index 4f946f7..3472f6a 100644 --- a/notifico-core/src/simpletransport.rs +++ b/notifico-core/src/simpletransport.rs @@ -75,6 +75,10 @@ impl EnginePlugin for SimpleTransportWrapper { .get_credential(context.project_id, &credential_selector) .await?; + if credential.transport != self.name() { + return Err(EngineError::InvalidCredentialFormat); + } + let contacts = if self.inner.has_contacts() { context.get_recipient()?.contacts.clone() } else { diff --git a/notificox/src/main.rs b/notificox/src/main.rs index 9739332..764c663 100644 --- a/notificox/src/main.rs +++ b/notificox/src/main.rs @@ -17,6 +17,7 @@ use notifico_template::source::DummyTemplateSource; use notifico_template::Templater; use notifico_transports::all_transports; use serde_json::{json, Map, Value}; +use std::str::FromStr; use std::sync::Arc; use tokio::task::JoinSet; use uuid::Uuid; @@ -74,7 +75,7 @@ async fn main() { let mut transport_registry = TransportRegistry::new(); let recorder = Arc::new(BaseRecorder::new()); - let credential = Credential::Short(credential); + let credential = Credential::from_str(&credential).unwrap(); let credentials = { let mut credentials = MemoryCredentialStorage::default(); @@ -113,9 +114,9 @@ async fn main() { let step = SerializedStep(step.as_object().cloned().unwrap()); pipeline.steps.push(step); } - let transport_name = credential.transport(); + let transport_name = credential.transport; let step = SerializedStep( - json!({ "step": transport_registry.get_step(transport_name).unwrap(), "credential": "notificox" }) + json!({ "step": transport_registry.get_step(&transport_name).unwrap(), "credential": "notificox" }) .as_object() .cloned() .unwrap(), diff --git a/transports/notifico-gotify/src/credentials.rs b/transports/notifico-gotify/src/credentials.rs index e28df00..b6d19e4 100644 --- a/transports/notifico-gotify/src/credentials.rs +++ b/transports/notifico-gotify/src/credentials.rs @@ -12,24 +12,9 @@ impl TryFrom for GotifyCredentials { type Error = EngineError; fn try_from(value: Credential) -> Result { - if value.transport() != Self::TRANSPORT_NAME { - return Err(EngineError::InvalidCredentialFormat)?; - } + let url = Url::parse(&value.value).map_err(|_| EngineError::InvalidCredentialFormat)?; - match value { - Credential::Long { value, .. } => { - Ok(serde_json::from_value(value) - .map_err(|_| EngineError::InvalidCredentialFormat)?) - } - Credential::Short(url) => { - let mut url = url.splitn(2, ":"); - let _ = url.next(); - let url = url.next().unwrap_or_default(); - let url = Url::parse(url).map_err(|_| EngineError::InvalidCredentialFormat)?; - - Ok(Self { url }) - } - } + Ok(Self { url }) } } diff --git a/transports/notifico-pushover/src/lib.rs b/transports/notifico-pushover/src/lib.rs index dac3cb7..5aaaae9 100644 --- a/transports/notifico-pushover/src/lib.rs +++ b/transports/notifico-pushover/src/lib.rs @@ -16,19 +16,7 @@ impl TryFrom for PushoverCredentials { type Error = EngineError; fn try_from(value: Credential) -> Result { - if value.transport() != Self::TRANSPORT_NAME { - return Err(EngineError::InvalidCredentialFormat)?; - } - - match value { - Credential::Long { value, .. } => { - Ok(serde_json::from_value(value) - .map_err(|_| EngineError::InvalidCredentialFormat)?) - } - Credential::Short(url) => Ok(Self { - token: url.strip_prefix("pushover:").unwrap_or_default().to_owned(), - }), - } + Ok(Self { token: value.value }) } } diff --git a/transports/notifico-slack/src/credentials.rs b/transports/notifico-slack/src/credentials.rs index 6296377..63da759 100644 --- a/transports/notifico-slack/src/credentials.rs +++ b/transports/notifico-slack/src/credentials.rs @@ -11,19 +11,7 @@ impl TryFrom for SlackCredentials { type Error = EngineError; fn try_from(value: Credential) -> Result { - if value.transport() != Self::TRANSPORT_NAME { - return Err(EngineError::InvalidCredentialFormat)?; - } - - match value { - Credential::Long { value, .. } => { - Ok(serde_json::from_value(value) - .map_err(|_| EngineError::InvalidCredentialFormat)?) - } - Credential::Short(url) => Ok(Self { - token: url.strip_prefix("slack:").unwrap_or_default().to_owned(), - }), - } + Ok(Self { token: value.value }) } } diff --git a/transports/notifico-smpp/src/credentials.rs b/transports/notifico-smpp/src/credentials.rs index a55580e..405312b 100644 --- a/transports/notifico-smpp/src/credentials.rs +++ b/transports/notifico-smpp/src/credentials.rs @@ -15,27 +15,14 @@ impl TryFrom for SmppServerCredentials { type Error = EngineError; fn try_from(value: Credential) -> Result { - if value.transport() != Self::TRANSPORT_NAME { - return Err(EngineError::InvalidCredentialFormat)?; - } - - match value { - Credential::Long { value, .. } => { - Ok(serde_json::from_value(value) - .map_err(|_| EngineError::InvalidCredentialFormat)?) - } - Credential::Short(url) => { - let url = url.strip_prefix("smpp:").unwrap_or_default(); - let url = String::from("smpp://") + url; - let url = Url::parse(&url).map_err(|_| EngineError::InvalidCredentialFormat)?; - Ok(Self { - host: url.host_str().unwrap_or_default().to_owned(), - port: url.port().unwrap_or_default(), - username: url.username().to_owned(), - password: url.password().unwrap_or_default().to_owned(), - }) - } - } + let url = String::from("smpp://") + &value.value; + let url = Url::parse(&url).map_err(|_| EngineError::InvalidCredentialFormat)?; + Ok(Self { + host: url.host_str().unwrap_or_default().to_owned(), + port: url.port().unwrap_or_default(), + username: url.username().to_owned(), + password: url.password().unwrap_or_default().to_owned(), + }) } } diff --git a/transports/notifico-smtp/src/credentials.rs b/transports/notifico-smtp/src/credentials.rs index 39f278b..d5e0702 100644 --- a/transports/notifico-smtp/src/credentials.rs +++ b/transports/notifico-smtp/src/credentials.rs @@ -18,33 +18,20 @@ impl TryFrom for SmtpServerCredentials { type Error = EngineError; fn try_from(value: Credential) -> Result { - if value.transport() != Self::TRANSPORT_NAME { - return Err(EngineError::InvalidCredentialFormat)?; - } - - match value { - Credential::Long { value, .. } => { - Ok(serde_json::from_value(value) - .map_err(|_| EngineError::InvalidCredentialFormat)?) - } - Credential::Short(url) => { - let url = url.strip_prefix("smtp:").unwrap_or_default(); - let url = String::from("smtp://") + url; - let url = Url::parse(&url).map_err(|_| EngineError::InvalidCredentialFormat)?; - let query: BTreeMap, Cow> = url.query_pairs().collect(); - let tls = query - .get("tls") - .map(|v| v.as_ref() == "true") - .unwrap_or(false); - Ok(Self { - host: url.host_str().unwrap_or_default().to_owned(), - port: url.port(), - username: url.username().to_owned(), - password: url.password().unwrap_or_default().to_owned(), - tls, - }) - } - } + let url = String::from("smtp://") + &value.value; + let url = Url::parse(&url).map_err(|_| EngineError::InvalidCredentialFormat)?; + let query: BTreeMap, Cow> = url.query_pairs().collect(); + let tls = query + .get("tls") + .map(|v| v.as_ref() == "true") + .unwrap_or(false); + Ok(Self { + host: url.host_str().unwrap_or_default().to_owned(), + port: url.port(), + username: url.username().to_owned(), + password: url.password().unwrap_or_default().to_owned(), + tls, + }) } } diff --git a/transports/notifico-telegram/src/lib.rs b/transports/notifico-telegram/src/lib.rs index f6d4510..24857fa 100644 --- a/transports/notifico-telegram/src/lib.rs +++ b/transports/notifico-telegram/src/lib.rs @@ -22,19 +22,7 @@ impl TryFrom for TelegramBotCredentials { type Error = EngineError; fn try_from(value: Credential) -> Result { - if value.transport() != Self::TRANSPORT_NAME { - return Err(EngineError::InvalidCredentialFormat)?; - } - - match value { - Credential::Long { value, .. } => { - Ok(serde_json::from_value(value) - .map_err(|_| EngineError::InvalidCredentialFormat)?) - } - Credential::Short(url) => Ok(Self { - token: url.strip_prefix("telegram:").unwrap_or_default().to_owned(), - }), - } + Ok(Self { token: value.value }) } } diff --git a/transports/notifico-whatsapp/src/credentials.rs b/transports/notifico-whatsapp/src/credentials.rs index f03d833..05f05c9 100644 --- a/transports/notifico-whatsapp/src/credentials.rs +++ b/transports/notifico-whatsapp/src/credentials.rs @@ -14,32 +14,19 @@ impl TryFrom for WhatsAppCredentials { type Error = EngineError; fn try_from(value: Credential) -> Result { - if value.transport() != Self::TRANSPORT_NAME { - return Err(EngineError::InvalidCredentialFormat)?; - } + static WABA_REGEX: OnceLock = OnceLock::new(); + let regex = WABA_REGEX.get_or_init(|| Regex::new("^([0-9]+):([0-9a-zA-Z]+)$").unwrap()); - match value { - Credential::Long { value, .. } => { - Ok(serde_json::from_value(value) - .map_err(|_| EngineError::InvalidCredentialFormat)?) - } - Credential::Short(url) => { - static WABA_REGEX: OnceLock = OnceLock::new(); - let regex = WABA_REGEX - .get_or_init(|| Regex::new("^waba:([0-9]+):([0-9a-zA-Z]+)$").unwrap()); + let caps = regex + .captures(&value.value) + .ok_or(EngineError::InvalidCredentialFormat)?; - let caps = regex - .captures(&url) - .ok_or(EngineError::InvalidCredentialFormat)?; - - Ok(Self { - phone_id: caps[0] - .parse() - .map_err(|_| EngineError::InvalidCredentialFormat)?, - token: caps[1].to_owned(), - }) - } - } + Ok(Self { + phone_id: caps[0] + .parse() + .map_err(|_| EngineError::InvalidCredentialFormat)?, + token: caps[1].to_owned(), + }) } }