Refactor error handling for confirm handler.

This commit is contained in:
LukeMathWalker 2021-05-12 22:33:43 +01:00
parent 2b3dae3a6a
commit 7b64134fe7
2 changed files with 36 additions and 15 deletions

View file

@ -196,7 +196,7 @@ impl std::fmt::Display for StoreTokenError {
}
}
fn error_chain_fmt(
pub fn error_chain_fmt(
e: &impl std::error::Error,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {

View file

@ -1,4 +1,7 @@
use actix_web::{web, HttpResponse};
use crate::routes::error_chain_fmt;
use actix_web::http::StatusCode;
use actix_web::{web, HttpResponse, ResponseError};
use anyhow::Context;
use sqlx::PgPool;
use uuid::Uuid;
@ -7,24 +10,42 @@ pub struct Parameters {
subscription_token: String,
}
#[derive(thiserror::Error)]
pub enum ConfirmationError {
#[error(transparent)]
UnexpectedError(#[from] anyhow::Error),
#[error("There is no subscriber associated with the provided token.")]
UnknownToken,
}
impl std::fmt::Debug for ConfirmationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
error_chain_fmt(self, f)
}
}
impl ResponseError for ConfirmationError {
fn status_code(&self) -> StatusCode {
match self {
Self::UnknownToken => StatusCode::UNAUTHORIZED,
Self::UnexpectedError(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}
#[tracing::instrument(name = "Confirm a pending subscriber", skip(parameters, pool))]
pub async fn confirm(
parameters: web::Query<Parameters>,
pool: web::Data<PgPool>,
) -> Result<HttpResponse, HttpResponse> {
let id = get_subscriber_id_from_token(&pool, &parameters.subscription_token)
) -> Result<HttpResponse, ConfirmationError> {
let subscriber_id = get_subscriber_id_from_token(&pool, &parameters.subscription_token)
.await
.map_err(|_| HttpResponse::InternalServerError().finish())?;
match id {
// Non-existing token!
None => Err(HttpResponse::Unauthorized().finish()),
Some(subscriber_id) => {
confirm_subscriber(&pool, subscriber_id)
.await
.map_err(|_| HttpResponse::InternalServerError().finish())?;
Ok(HttpResponse::Ok().finish())
}
}
.context("Failed to retrieve the subscriber id associated with the provided token.")?
.ok_or(ConfirmationError::UnknownToken)?;
confirm_subscriber(&pool, subscriber_id)
.await
.context("Failed to update the subscriber status to `confirmed`.")?;
Ok(HttpResponse::Ok().finish())
}
#[tracing::instrument(name = "Mark subscriber as confirmed", skip(subscriber_id, pool))]