doido_auth/controllers/
confirmations.rs1use crate::confirmable;
4use doido_auth_macros::auth_controller;
5use doido_core::Result;
6use serde::Deserialize;
7use std::marker::PhantomData;
8
9pub struct AuthConfirmations<U>(PhantomData<U>);
11
12#[derive(Debug, Deserialize)]
13pub struct ConfirmQuery {
14 #[serde(default)]
15 pub confirmation_token: String,
16}
17
18#[derive(Debug, Deserialize)]
19pub struct ResendForm {
20 pub email: String,
21}
22
23#[auth_controller]
24impl<U> AuthConfirmations<U>
25where
26 U: Send + Sync + 'static,
27{
28 pub async fn show(ctx: doido_controller::Context) -> Result<doido_controller::Response> {
30 let json = ctx.wants_json();
31 let token = ctx
32 .params::<ConfirmQuery>()
33 .map(|q| q.confirmation_token)
34 .unwrap_or_default();
35
36 let confirmed = confirmable::confirm(ctx.db(), &token).await?;
37 if !confirmed {
38 return if json {
39 Ok(ctx.status(422))
40 } else {
41 Ok(ctx.render(
42 "auth/sign_in",
43 serde_json::json!({ "error": "Confirmation link is invalid or has expired" }),
44 ))
45 };
46 }
47 if json {
48 Ok(ctx.json(serde_json::json!({ "status": "confirmed" })))
49 } else {
50 Ok(ctx.redirect_to("/users/sign_in"))
51 }
52 }
53
54 pub async fn create(mut ctx: doido_controller::Context) -> Result<doido_controller::Response> {
57 let json = ctx.wants_json();
58 let form: ResendForm = if json {
59 ctx.body_json().await?
60 } else {
61 ctx.form().await?
62 };
63
64 if let Some(token) = confirmable::generate_confirmation(ctx.db(), &form.email).await? {
65 let _ = confirmable::send_confirmation_email(&form.email, &token).await;
66 }
67
68 if json {
69 Ok(ctx.json(serde_json::json!({ "status": "confirmation_sent" })))
70 } else {
71 Ok(ctx.render(
72 "auth/sign_in",
73 serde_json::json!({ "notice": "If your email exists, a confirmation link was sent." }),
74 ))
75 }
76 }
77}