Update telemetry
This commit is contained in:
@@ -31,16 +31,16 @@ pub async fn change_password(
|
||||
password: form.current_password,
|
||||
};
|
||||
if form.new_password.expose_secret() != form.new_password_check.expose_secret() {
|
||||
Err(AdminError::ChangePassword(
|
||||
"You entered two different passwords - the field values must match.".to_string(),
|
||||
)
|
||||
Err(AdminError::ChangePassword(anyhow::anyhow!(
|
||||
"You entered two different passwords - the field values must match."
|
||||
))
|
||||
.into())
|
||||
} else if let Err(e) = validate_credentials(credentials, &connection_pool).await {
|
||||
match e {
|
||||
AuthError::UnexpectedError(error) => Err(AdminError::UnexpectedError(error).into()),
|
||||
AuthError::InvalidCredentials(_) => Err(AdminError::ChangePassword(
|
||||
"The current password is incorrect.".to_string(),
|
||||
)
|
||||
AuthError::InvalidCredentials(_) => Err(AdminError::ChangePassword(anyhow::anyhow!(
|
||||
"The current password is incorrect."
|
||||
))
|
||||
.into()),
|
||||
}
|
||||
} else if let Err(e) = verify_password(form.new_password.expose_secret()) {
|
||||
@@ -48,7 +48,7 @@ pub async fn change_password(
|
||||
} else {
|
||||
authentication::change_password(user_id, form.new_password, &connection_pool)
|
||||
.await
|
||||
.map_err(|e| AdminError::ChangePassword(e.to_string()))?;
|
||||
.map_err(AdminError::ChangePassword)?;
|
||||
let template = MessageTemplate::Success {
|
||||
message: "Your password has been changed.".to_string(),
|
||||
};
|
||||
@@ -56,9 +56,9 @@ pub async fn change_password(
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_password(password: &str) -> Result<(), String> {
|
||||
fn verify_password(password: &str) -> Result<(), anyhow::Error> {
|
||||
if password.len() < 12 || password.len() > 128 {
|
||||
return Err("The password must contain between 12 and 128 characters.".into());
|
||||
anyhow::bail!("The password must contain between 12 and 128 characters.");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ pub async fn admin_dashboard(
|
||||
Ok(Html(template.render().unwrap()).into_response())
|
||||
}
|
||||
|
||||
#[tracing::instrument("Computing dashboard stats", skip_all)]
|
||||
async fn get_stats(connection_pool: &PgPool) -> Result<DashboardStats, anyhow::Error> {
|
||||
let subscribers =
|
||||
sqlx::query_scalar!("SELECT count(*) FROM subscriptions WHERE status = 'confirmed'")
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::{
|
||||
authentication::AuthenticatedUser,
|
||||
idempotency::{IdempotencyKey, save_response, try_processing},
|
||||
@@ -15,6 +13,7 @@ use axum::{
|
||||
response::{Html, IntoResponse, Response},
|
||||
};
|
||||
use sqlx::{Executor, Postgres, Transaction};
|
||||
use std::fmt::Display;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
@@ -25,13 +24,14 @@ pub struct BodyData {
|
||||
idempotency_key: String,
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(name = "Creating newsletter isue", skip_all, fields(issue_id = tracing::field::Empty))]
|
||||
pub async fn insert_newsletter_issue(
|
||||
transaction: &mut Transaction<'static, Postgres>,
|
||||
title: &str,
|
||||
email_template: &dyn EmailTemplate,
|
||||
) -> Result<Uuid, sqlx::Error> {
|
||||
let newsletter_issue_id = Uuid::new_v4();
|
||||
tracing::Span::current().record("issue_id", newsletter_issue_id.to_string());
|
||||
let query = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO newsletter_issues (
|
||||
@@ -48,6 +48,7 @@ pub async fn insert_newsletter_issue(
|
||||
Ok(newsletter_issue_id)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EmailType {
|
||||
NewPost,
|
||||
Newsletter,
|
||||
@@ -62,7 +63,7 @@ impl Display for EmailType {
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(name = "Adding new task to queue", skip(transaction))]
|
||||
pub async fn enqueue_delivery_tasks(
|
||||
transaction: &mut Transaction<'static, Postgres>,
|
||||
newsletter_issue_id: Uuid,
|
||||
@@ -87,7 +88,7 @@ pub async fn enqueue_delivery_tasks(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "Publishing a newsletter", skip(connection_pool, form))]
|
||||
#[tracing::instrument(name = "Publishing a newsletter", skip_all, fields(title = %form.title))]
|
||||
pub async fn publish_newsletter(
|
||||
State(AppState {
|
||||
connection_pool,
|
||||
@@ -134,12 +135,12 @@ pub async fn publish_newsletter(
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
fn validate_form(form: &BodyData) -> Result<(), &'static str> {
|
||||
fn validate_form(form: &BodyData) -> Result<(), anyhow::Error> {
|
||||
if form.title.is_empty() {
|
||||
return Err("The title was empty.");
|
||||
anyhow::bail!("The title was empty.");
|
||||
}
|
||||
if form.html.is_empty() || form.text.is_empty() {
|
||||
return Err("The content was empty.");
|
||||
anyhow::bail!("The content was empty.");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -33,7 +33,11 @@ fn validate_form(form: &CreatePostForm) -> Result<(), anyhow::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "Creating a post", skip(connection_pool, form))]
|
||||
#[tracing::instrument(
|
||||
name = "Publishing new blog post",
|
||||
skip(connection_pool, base_url, form)
|
||||
fields(title = %form.title)
|
||||
)]
|
||||
pub async fn create_post(
|
||||
State(AppState {
|
||||
connection_pool,
|
||||
@@ -79,10 +83,7 @@ pub async fn create_post(
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "Saving new post in the database",
|
||||
skip(transaction, title, content, author)
|
||||
)]
|
||||
#[tracing::instrument(name = "Saving new blog post in the database", skip_all)]
|
||||
pub async fn insert_post(
|
||||
transaction: &mut Transaction<'static, Postgres>,
|
||||
title: &str,
|
||||
@@ -105,10 +106,7 @@ pub async fn insert_post(
|
||||
Ok(post_id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "Creating newsletter for new post",
|
||||
skip(transaction, post_title, post_id)
|
||||
)]
|
||||
#[tracing::instrument(name = "Creating newsletter for new post", skip_all)]
|
||||
pub async fn create_newsletter(
|
||||
transaction: &mut Transaction<'static, Postgres>,
|
||||
base_url: &str,
|
||||
|
||||
@@ -15,6 +15,10 @@ use uuid::Uuid;
|
||||
|
||||
const SUBS_PER_PAGE: i64 = 5;
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "Retrieving most recent subscribers from database",
|
||||
skip(connection_pool)
|
||||
)]
|
||||
pub async fn get_subscribers_page(
|
||||
State(AppState {
|
||||
connection_pool, ..
|
||||
@@ -38,34 +42,52 @@ pub async fn get_subscribers_page(
|
||||
Ok(Html(template.render().unwrap()).into_response())
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "Deleting subscriber from database",
|
||||
skip(connection_pool),
|
||||
fields(email=tracing::field::Empty)
|
||||
)]
|
||||
pub async fn delete_subscriber(
|
||||
State(AppState {
|
||||
connection_pool, ..
|
||||
}): State<AppState>,
|
||||
Path(subscriber_id): Path<Uuid>,
|
||||
) -> Result<Response, AppError> {
|
||||
let res = sqlx::query!("DELETE FROM subscriptions WHERE id = $1", subscriber_id)
|
||||
.execute(&connection_pool)
|
||||
.await
|
||||
.context("Failed to delete subscriber from database.")
|
||||
.map_err(AppError::unexpected_message)?;
|
||||
if res.rows_affected() > 1 {
|
||||
let res = sqlx::query!(
|
||||
"DELETE FROM subscriptions WHERE id = $1 RETURNING email",
|
||||
subscriber_id
|
||||
)
|
||||
.fetch_optional(&connection_pool)
|
||||
.await
|
||||
.context("Failed to delete subscriber from database.")
|
||||
.map_err(AppError::unexpected_message)?;
|
||||
if let Some(record) = res {
|
||||
tracing::Span::current().record("email", tracing::field::display(&record.email));
|
||||
let template = MessageTemplate::Success {
|
||||
message: format!(
|
||||
"The subscriber with email '{}' has been deleted.",
|
||||
record.email
|
||||
),
|
||||
};
|
||||
Ok(template.render().unwrap().into_response())
|
||||
} else {
|
||||
Err(AppError::unexpected_message(anyhow::anyhow!(
|
||||
"We could not find the subscriber in the database."
|
||||
)))
|
||||
} else {
|
||||
let template = MessageTemplate::Success {
|
||||
message: "The subscriber has been deleted.".into(),
|
||||
};
|
||||
Ok(template.render().unwrap().into_response())
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "Retrieving next subscribers in database",
|
||||
skip(connection_pool),
|
||||
fields(offset = tracing::field::Empty)
|
||||
)]
|
||||
pub async fn get_subs(
|
||||
connection_pool: &PgPool,
|
||||
page: i64,
|
||||
) -> Result<Vec<SubscriberEntry>, sqlx::Error> {
|
||||
let offset = (page - 1) * SUBS_PER_PAGE;
|
||||
tracing::Span::current().record("offset", tracing::field::display(&offset));
|
||||
let subscribers = sqlx::query_as!(
|
||||
SubscriberEntry,
|
||||
"SELECT * FROM subscriptions ORDER BY subscribed_at DESC LIMIT $1 OFFSET $2",
|
||||
|
||||
Reference in New Issue
Block a user