feat: load billing adapters #125
11 changed files with 228 additions and 2 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -4172,6 +4172,21 @@ version = "0.2.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "twilio_client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix-rt",
|
||||
"derive-getters",
|
||||
"derive_builder 0.20.2",
|
||||
"derive_more 0.99.18",
|
||||
"log",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
|
@ -4445,6 +4460,7 @@ dependencies = [
|
|||
"time",
|
||||
"tracing",
|
||||
"tracing-actix-web",
|
||||
"twilio_client",
|
||||
"url",
|
||||
"uuid",
|
||||
"validator 0.18.1",
|
||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[workspace]
|
||||
exclude = ["utils/db-migrations"] #, "utils/cache-bust"]
|
||||
members = [".", "mailpit_client"]
|
||||
members = [".", "mailpit_client", "twilio_client"]
|
||||
|
||||
[dependencies]
|
||||
actix-identity = "0.8.0"
|
||||
|
@ -36,7 +36,8 @@ tracing = { version = "0.1.40", features = ["log"] }
|
|||
tracing-actix-web = "0.7.10"
|
||||
url = { version = "2.5.0", features = ["serde"] }
|
||||
uuid = { version = "1.10.0", features = ["v4", "serde"] }
|
||||
validator = { version = "0.18.1", features = ["derive"] }
|
||||
validator = { version = "0.19.0", features = ["derive"] }
|
||||
twilio_client = { path = "./twilio_client" }
|
||||
|
||||
[dev-dependencies]
|
||||
#reqwest = { version = "0.12.4", features = ["json"] }
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
|
||||
pub mod db;
|
||||
pub mod mailer;
|
||||
pub mod phone;
|
||||
|
|
5
src/identity/adapters/output/phone/mod.rs
Normal file
5
src/identity/adapters/output/phone/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pub mod twilio;
|
|
@ -0,0 +1,57 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use lettre::{message::header::ContentType, AsyncTransport, Message};
|
||||
|
||||
use super::*;
|
||||
use crate::identity::application::port::output::phone::{account_login_otp::*, errors::*};
|
||||
use crate::identity::domain::employee_aggregate::PhoneNumber;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AccountLoginOTPOutPhonePort for Phone {
|
||||
async fn account_login_otp(&self, to: &PhoneNumber, otp: usize) -> OutPhonePortResult<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use url::Url;
|
||||
|
||||
use mailpit_client::*;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_phone_account_validation_otp() {
|
||||
// let username = "batman";
|
||||
// let email = "batman@account_validation_otp.example.com";
|
||||
// let validation_secret = "dafsdfasecret";
|
||||
//
|
||||
// let settings = crate::settings::tests::get_settings().await;
|
||||
// let m = Lettrephone::new(&settings);
|
||||
//
|
||||
// m.account_validation_otp(email, username, validation_secret)
|
||||
// .await
|
||||
// .unwrap();
|
||||
//
|
||||
// let mailpit_url =
|
||||
// std::env::var("MAILPIT_URL").expect("Please set mailpit instance URL in MAILPIT_URL");
|
||||
// let mc = MailPitHTTPClientBuilder::default()
|
||||
// .url(Url::parse(&mailpit_url).unwrap())
|
||||
// .build()
|
||||
// .unwrap();
|
||||
//
|
||||
// let mailpit_email = mc.get_email_addressed_to(email).await;
|
||||
//
|
||||
// assert!(mailpit_email.text().contains(validation_secret));
|
||||
// assert!(mailpit_email.text().contains(username));
|
||||
// assert!(mailpit_email
|
||||
// .to()
|
||||
// .iter()
|
||||
// .any(|t| t.address() == email && t.name() == username));
|
||||
//
|
||||
// mc.delete_email(mailpit_email).await;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use lettre::{message::header::ContentType, AsyncTransport, Message};
|
||||
|
||||
use super::*;
|
||||
use crate::identity::application::port::output::phone::{account_validation_otp::*, errors::*};
|
||||
use crate::identity::domain::employee_aggregate::PhoneNumber;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AccountValidationOTPOutPhonePort for Phone {
|
||||
async fn account_validation_otp(&self, to: &PhoneNumber, otp: usize) -> OutPhonePortResult<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use url::Url;
|
||||
|
||||
use mailpit_client::*;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_phone_account_validation_otp() {
|
||||
// let username = "batman";
|
||||
// let email = "batman@account_validation_otp.example.com";
|
||||
// let validation_secret = "dafsdfasecret";
|
||||
//
|
||||
// let settings = crate::settings::tests::get_settings().await;
|
||||
// let m = Lettrephone::new(&settings);
|
||||
//
|
||||
// m.account_validation_otp(email, username, validation_secret)
|
||||
// .await
|
||||
// .unwrap();
|
||||
//
|
||||
// let mailpit_url =
|
||||
// std::env::var("MAILPIT_URL").expect("Please set mailpit instance URL in MAILPIT_URL");
|
||||
// let mc = MailPitHTTPClientBuilder::default()
|
||||
// .url(Url::parse(&mailpit_url).unwrap())
|
||||
// .build()
|
||||
// .unwrap();
|
||||
//
|
||||
// let mailpit_email = mc.get_email_addressed_to(email).await;
|
||||
//
|
||||
// assert!(mailpit_email.text().contains(validation_secret));
|
||||
// assert!(mailpit_email.text().contains(username));
|
||||
// assert!(mailpit_email
|
||||
// .to()
|
||||
// .iter()
|
||||
// .any(|t| t.address() == email && t.name() == username));
|
||||
//
|
||||
// mc.delete_email(mailpit_email).await;
|
||||
}
|
||||
}
|
1
src/identity/adapters/output/phone/twilio/errors.rs
Normal file
1
src/identity/adapters/output/phone/twilio/errors.rs
Normal file
|
@ -0,0 +1 @@
|
|||
|
29
src/identity/adapters/output/phone/twilio/mod.rs
Normal file
29
src/identity/adapters/output/phone/twilio/mod.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
use std::sync::Arc;
|
||||
|
||||
use twilio_client::{TwilioClient, TwilioClientBuilder};
|
||||
|
||||
use crate::settings::Settings;
|
||||
|
||||
mod account_login_otp;
|
||||
mod account_validation_otp;
|
||||
mod errors;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Phone {
|
||||
tx: TwilioClient,
|
||||
}
|
||||
|
||||
impl Phone {
|
||||
pub fn new(s: &Settings) -> Self {
|
||||
let tx = TwilioClientBuilder::default()
|
||||
.auth_token(s.phone.twilio_auth_token.clone())
|
||||
.account_id(s.phone.twilio_account_id.clone())
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
Self { tx }
|
||||
}
|
||||
}
|
1
twilio_client/.gitignore
vendored
Normal file
1
twilio_client/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
target/
|
15
twilio_client/Cargo.toml
Normal file
15
twilio_client/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "twilio_client"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
reqwest = { version = "0.12.4", features = ["json", "native-tls-vendored"] }
|
||||
serde = { version = "1.0.201", features = ["derive"] }
|
||||
serde_json = "1.0.117"
|
||||
actix-rt = "2.9.0"
|
||||
derive-getters = "0.5.0"
|
||||
derive_more = "0.99.17"
|
||||
log = "0.4.21"
|
||||
derive_builder = "0.20.0"
|
||||
url = { version = "2.5.0", features = ["serde"] }
|
43
twilio_client/src/lib.rs
Normal file
43
twilio_client/src/lib.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use derive_builder::Builder;
|
||||
#[allow(unused_imports)]
|
||||
use log::*;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(test)]
|
||||
use println as info;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Builder)]
|
||||
pub struct TwilioClient {
|
||||
auth_token: String,
|
||||
account_id: String,
|
||||
#[builder(default = "Client::default()")]
|
||||
client: Client,
|
||||
}
|
||||
|
||||
impl TwilioClient {
|
||||
async fn send_sms(from: &str, to: &str, msg: &str) -> Result<(), String> {
|
||||
unimplemented!()
|
||||
// Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
//pub fn add(left: u64, right: u64) -> u64 {
|
||||
// left + right
|
||||
//}
|
||||
//
|
||||
//#[cfg(test)]
|
||||
//mod tests {
|
||||
// use super::*;
|
||||
//
|
||||
// #[test]
|
||||
// fn it_works() {
|
||||
// let result = add(2, 2);
|
||||
// assert_eq!(result, 4);
|
||||
// }
|
||||
//}
|
Loading…
Reference in a new issue