aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-server
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@atuin.sh>2026-01-27 13:56:18 -0800
committerGitHub <noreply@github.com>2026-01-27 13:56:18 -0800
commite2b421c88479857831e938acb311aef5127f38b4 (patch)
tree0ff160c378f1c151ecb30fa0329aafcee72b8d9d /crates/atuin-server
parentchore(deps): cleanup of dep versions (#3106) (diff)
downloadatuin-e2b421c88479857831e938acb311aef5127f38b4.zip
feat: remove user verification functionality (#3108)
<!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## 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>
Diffstat (limited to 'crates/atuin-server')
-rw-r--r--crates/atuin-server/Cargo.toml1
-rw-r--r--crates/atuin-server/src/handlers/user.rs105
-rw-r--r--crates/atuin-server/src/router.rs5
-rw-r--r--crates/atuin-server/src/settings.rs29
4 files changed, 0 insertions, 140 deletions
diff --git a/crates/atuin-server/Cargo.toml b/crates/atuin-server/Cargo.toml
index 915ceb14..ea647f38 100644
--- a/crates/atuin-server/Cargo.toml
+++ b/crates/atuin-server/Cargo.toml
@@ -32,4 +32,3 @@ argon2 = "0.5"
semver = { workspace = true }
metrics-exporter-prometheus = "0.18"
metrics = "0.24"
-postmark = {version= "0.11", features=["reqwest", "reqwest-rustls-tls"]}
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<DB: Database>(
Ok(Json(DeleteUserResponse {}))
}
-#[instrument(skip_all, fields(user.id = user.id))]
-pub async fn send_verification<DB: Database>(
- UserAuth(user): UserAuth,
- state: State<AppState<DB>>,
-) -> Result<Json<SendVerificationResponse>, 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<DB: Database>(
- UserAuth(user): UserAuth,
- state: State<AppState<DB>>,
- Json(token_request): Json<VerificationTokenRequest>,
-) -> Result<Json<VerificationTokenResponse>, 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<DB: Database>(
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<DB: Database>(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<String>,
-}
-
-#[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<String>,
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")