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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
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]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
@ -4445,6 +4460,7 @@ dependencies = [
|
||||||
"time",
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-actix-web",
|
"tracing-actix-web",
|
||||||
|
"twilio_client",
|
||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
"validator 0.18.1",
|
"validator 0.18.1",
|
||||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
exclude = ["utils/db-migrations"] #, "utils/cache-bust"]
|
exclude = ["utils/db-migrations"] #, "utils/cache-bust"]
|
||||||
members = [".", "mailpit_client"]
|
members = [".", "mailpit_client", "twilio_client"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-identity = "0.8.0"
|
actix-identity = "0.8.0"
|
||||||
|
@ -36,7 +36,8 @@ tracing = { version = "0.1.40", features = ["log"] }
|
||||||
tracing-actix-web = "0.7.10"
|
tracing-actix-web = "0.7.10"
|
||||||
url = { version = "2.5.0", features = ["serde"] }
|
url = { version = "2.5.0", features = ["serde"] }
|
||||||
uuid = { version = "1.10.0", features = ["v4", "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]
|
[dev-dependencies]
|
||||||
#reqwest = { version = "0.12.4", features = ["json"] }
|
#reqwest = { version = "0.12.4", features = ["json"] }
|
||||||
|
|
|
@ -4,3 +4,4 @@
|
||||||
|
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod mailer;
|
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