this repo has no description
1use axum::{Json, extract::State, http::StatusCode};
2use serde::{Deserialize, Serialize};
3use serde_json::json;
4use tracing::{info, warn};
5
6use crate::state::AppState;
7
8#[derive(Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct VerifyMigrationEmailInput {
11 pub token: String,
12 pub email: String,
13}
14
15#[derive(Serialize)]
16#[serde(rename_all = "camelCase")]
17pub struct VerifyMigrationEmailOutput {
18 pub success: bool,
19 pub did: String,
20}
21
22pub async fn verify_migration_email(
23 State(state): State<AppState>,
24 Json(input): Json<VerifyMigrationEmailInput>,
25) -> Result<Json<VerifyMigrationEmailOutput>, (StatusCode, Json<serde_json::Value>)> {
26 let token_input = super::verify_token::VerifyTokenInput {
27 token: input.token,
28 identifier: input.email,
29 };
30
31 let result = super::verify_token::verify_token_internal(&state, None, token_input).await?;
32
33 Ok(Json(VerifyMigrationEmailOutput {
34 success: result.success,
35 did: result.did.clone(),
36 }))
37}
38
39#[derive(Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct ResendMigrationVerificationInput {
42 pub email: String,
43}
44
45#[derive(Serialize)]
46#[serde(rename_all = "camelCase")]
47pub struct ResendMigrationVerificationOutput {
48 pub sent: bool,
49}
50
51pub async fn resend_migration_verification(
52 State(state): State<AppState>,
53 Json(input): Json<ResendMigrationVerificationInput>,
54) -> Result<Json<ResendMigrationVerificationOutput>, (StatusCode, Json<serde_json::Value>)> {
55 let email = input.email.trim().to_lowercase();
56
57 let user = sqlx::query!(
58 "SELECT id, did, email, email_verified, handle FROM users WHERE LOWER(email) = $1",
59 email
60 )
61 .fetch_optional(&state.db)
62 .await
63 .map_err(|e| {
64 warn!(error = %e, "Database error during resend verification");
65 (
66 StatusCode::INTERNAL_SERVER_ERROR,
67 Json(json!({ "error": "InternalError", "message": "Database error" })),
68 )
69 })?;
70
71 let user = match user {
72 Some(u) => u,
73 None => {
74 return Ok(Json(ResendMigrationVerificationOutput { sent: true }));
75 }
76 };
77
78 if user.email_verified {
79 return Ok(Json(ResendMigrationVerificationOutput { sent: true }));
80 }
81
82 let hostname = std::env::var("PDS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string());
83 let token = crate::auth::verification_token::generate_migration_token(&user.did, &email);
84 let formatted_token = crate::auth::verification_token::format_token_for_display(&token);
85
86 if let Err(e) = crate::comms::enqueue_migration_verification(
87 &state.db,
88 user.id,
89 &email,
90 &formatted_token,
91 &hostname,
92 )
93 .await
94 {
95 warn!(error = %e, "Failed to enqueue migration verification email");
96 }
97
98 info!(did = %user.did, "Resent migration verification email");
99
100 Ok(Json(ResendMigrationVerificationOutput { sent: true }))
101}