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