From e2b421c88479857831e938acb311aef5127f38b4 Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Tue, 27 Jan 2026 13:56:18 -0800 Subject: feat: remove user verification functionality (#3108) ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- crates/atuin-server/src/handlers/user.rs | 105 ------------------------------- crates/atuin-server/src/router.rs | 5 -- crates/atuin-server/src/settings.rs | 29 --------- 3 files changed, 139 deletions(-) (limited to 'crates/atuin-server/src') diff --git a/crates/atuin-server/src/handlers/user.rs b/crates/atuin-server/src/handlers/user.rs index 4edd1787..c6fec51e 100644 --- a/crates/atuin-server/src/handlers/user.rs +++ b/crates/atuin-server/src/handlers/user.rs @@ -13,8 +13,6 @@ use axum::{ }; use metrics::counter; -use postmark::{Query, reqwest::PostmarkClient}; - use rand::rngs::OsRng; use tracing::{debug, error, info, instrument}; @@ -178,109 +176,6 @@ pub async fn delete( Ok(Json(DeleteUserResponse {})) } -#[instrument(skip_all, fields(user.id = user.id))] -pub async fn send_verification( - UserAuth(user): UserAuth, - state: State>, -) -> Result, ErrorResponseStatus<'static>> { - let settings = state.0.settings; - debug!("request to verify user {}", user.username); - - if !settings.mail.enabled { - return Ok(Json(SendVerificationResponse { - email_sent: false, - verified: false, - })); - } - - if user.verified.is_some() { - return Ok(Json(SendVerificationResponse { - email_sent: false, - verified: true, - })); - } - - // TODO: if we ever add another mail provider, can match on them all here. - let postmark_token = match settings.mail.postmark.token { - Some(token) => token, - _ => { - error!("Failed to verify email: got None for postmark token"); - return Err(ErrorResponse::reply("mail not configured") - .with_status(StatusCode::INTERNAL_SERVER_ERROR)); - } - }; - - let db = &state.0.database; - - let verification_token = db - .user_verification_token(user.id) - .await - .expect("Failed to verify"); - - debug!("Generated verification token, emailing user"); - - let client = PostmarkClient::builder() - .base_url("https://api.postmarkapp.com/") - .server_token(postmark_token) - .build(); - - let req = postmark::api::email::SendEmailRequest::builder() - .from(settings.mail.verification.from) - .subject(settings.mail.verification.subject) - .to(user.email) - .body(postmark::api::Body::text(format!( - "Please run the following command to finalize your Atuin account verification. It is valid for 15 minutes:\n\natuin account verify --token '{verification_token}'" - ))) - .build(); - - req.execute(&client) - .await - .expect("postmark email request failed"); - - debug!("Email sent"); - - Ok(Json(SendVerificationResponse { - email_sent: true, - verified: false, - })) -} - -#[instrument(skip_all, fields(user.id = user.id))] -pub async fn verify_user( - UserAuth(user): UserAuth, - state: State>, - Json(token_request): Json, -) -> Result, ErrorResponseStatus<'static>> { - let db = state.0.database; - - if user.verified.is_some() { - return Ok(Json(VerificationTokenResponse { verified: true })); - } - - let token = db.user_verification_token(user.id).await.map_err(|e| { - error!("Failed to read user token: {e}"); - - ErrorResponse::reply("Failed to verify").with_status(StatusCode::INTERNAL_SERVER_ERROR) - })?; - - if token_request.token == token { - db.verify_user(user.id).await.map_err(|e| { - error!("Failed to verify user: {e}"); - - ErrorResponse::reply("Failed to verify").with_status(StatusCode::INTERNAL_SERVER_ERROR) - })?; - } else { - info!( - "Incorrect verification token {} vs {}", - token_request.token, token - ); - - return Ok(Json(VerificationTokenResponse { verified: false })); - } - - Ok(Json(VerificationTokenResponse { verified: true })) -} - #[instrument(skip_all, fields(user.id = user.id, change_password))] pub async fn change_password( UserAuth(mut user): UserAuth, diff --git a/crates/atuin-server/src/router.rs b/crates/atuin-server/src/router.rs index 9d4f7d44..0c41d5e6 100644 --- a/crates/atuin-server/src/router.rs +++ b/crates/atuin-server/src/router.rs @@ -134,11 +134,6 @@ pub fn router(database: DB, settings: Settings) -> Router { .route("/record", get(handlers::record::index)) .route("/record/next", get(handlers::record::next)) .route("/api/v0/me", get(handlers::v0::me::get)) - .route("/api/v0/account/verify", post(handlers::user::verify_user)) - .route( - "/api/v0/account/send-verification", - post(handlers::user::send_verification), - ) .route("/api/v0/record", post(handlers::v0::record::post)) .route("/api/v0/record", get(handlers::v0::record::index)) .route("/api/v0/record/next", get(handlers::v0::record::next)) diff --git a/crates/atuin-server/src/settings.rs b/crates/atuin-server/src/settings.rs index 98d1d69f..3a612be9 100644 --- a/crates/atuin-server/src/settings.rs +++ b/crates/atuin-server/src/settings.rs @@ -8,33 +8,6 @@ use serde::{Deserialize, Serialize}; static EXAMPLE_CONFIG: &str = include_str!("../server.toml"); -#[derive(Default, Clone, Debug, Deserialize, Serialize)] -pub struct Mail { - #[serde(alias = "enable")] - pub enabled: bool, - - /// Configuration for the postmark api client - /// This is what we use for Atuin Cloud, the forum, etc. - #[serde(default)] - pub postmark: Postmark, - - #[serde(default)] - pub verification: MailVerification, -} - -#[derive(Default, Clone, Debug, Deserialize, Serialize)] -pub struct Postmark { - #[serde(alias = "token")] - pub token: Option, -} - -#[derive(Default, Clone, Debug, Deserialize, Serialize)] -pub struct MailVerification { - #[serde(alias = "enable")] - pub from: String, - pub subject: String, -} - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Metrics { #[serde(alias = "enabled")] @@ -65,7 +38,6 @@ pub struct Settings { pub register_webhook_url: Option, pub register_webhook_username: String, pub metrics: Metrics, - pub mail: Mail, /// Enable legacy sync v1 routes (history-based sync) /// Set to false to use only the newer record-based sync @@ -108,7 +80,6 @@ impl Settings { .set_default("metrics.enable", false)? .set_default("metrics.host", "127.0.0.1")? .set_default("metrics.port", 9001)? - .set_default("mail.enable", false)? .set_default("sync_v1_enabled", true)? .add_source( Environment::with_prefix("atuin") -- cgit v1.3.1