60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
use crate::errors::ZTPError;
|
|
use crate::session_id::SessionId;
|
|
use axum::{http::StatusCode, Extension, Form};
|
|
use chrono::{DateTime, Utc};
|
|
use sqlx::types::Uuid;
|
|
use sqlx::PgPool;
|
|
|
|
#[derive(serde::Deserialize)]
|
|
pub(crate) struct NewSubscription {
|
|
pub email: String,
|
|
pub name: String,
|
|
}
|
|
|
|
#[derive(serde::Deserialize, serde::Serialize, sqlx::FromRow)]
|
|
struct Subscription {
|
|
pub id: Uuid,
|
|
pub email: String,
|
|
pub name: String,
|
|
pub subscribed_at: DateTime<Utc>,
|
|
}
|
|
|
|
impl From<&NewSubscription> for Subscription {
|
|
fn from(s: &NewSubscription) -> Self {
|
|
Subscription {
|
|
id: Uuid::new_v4(),
|
|
email: s.email.clone(),
|
|
name: s.name.clone(),
|
|
subscribed_at: Utc::now(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) async fn subscribe(
|
|
Extension(session): Extension<SessionId>,
|
|
Extension(pool): Extension<PgPool>,
|
|
payload: Option<Form<NewSubscription>>,
|
|
) -> Result<(StatusCode, ()), ZTPError> {
|
|
if let Some(payload) = payload {
|
|
let sql = "INSERT INTO subscriptions (id, email, name, subscribed_at) VALUES ($1, $2, $3, $4);".to_string();
|
|
let subscription: Subscription = (&(payload.0)).into();
|
|
|
|
tracing::info!(
|
|
"request_id {} - Adding '{}' as a new subscriber.",
|
|
session.0.to_string(),
|
|
subscription.name
|
|
);
|
|
|
|
sqlx::query(&sql)
|
|
.bind(subscription.id)
|
|
.bind(subscription.email)
|
|
.bind(subscription.name)
|
|
.bind(subscription.subscribed_at)
|
|
.execute(&pool)
|
|
.await
|
|
.map_or(Err(ZTPError::DuplicateEmail), |_| Ok((StatusCode::OK, ())))
|
|
} else {
|
|
Err(ZTPError::FormIncomplete)
|
|
}
|
|
}
|