change in confirm mechanism

This commit is contained in:
Mateusz Gruszczyński
2026-07-28 10:17:45 +02:00
parent d38b5b0b51
commit c8d441fa76
6 changed files with 31 additions and 8 deletions
Generated
+1 -1
View File
@@ -2581,7 +2581,7 @@ dependencies = [
[[package]]
name = "rustpad"
version = "0.1.13"
version = "0.1.14"
dependencies = [
"argon2",
"aws-config",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "rustpad"
version = "0.1.13"
version = "0.1.14"
edition = "2024"
rust-version = "1.94"
description = "Collaborative Markdown notepad built with Axum, WebSockets and SQLite, PostgreSQL and MySQL"
+1 -1
View File
@@ -103,7 +103,7 @@ pub fn router(
)
.route(
"/share-invitations/{token}/accept",
get(auth::accept_share_invitation),
get(home).post(auth::accept_share_invitation),
)
.route("/api/auth/password-reset", post(auth::request_reset))
.route(
+2 -3
View File
@@ -9,7 +9,6 @@ use axum::{
Json,
extract::{Path as AxumPath, State},
http::{HeaderMap, StatusCode},
response::Redirect,
};
use chrono::{Duration, Utc};
use lettre::{
@@ -1261,7 +1260,7 @@ pub async fn share_resource_users(
pub async fn accept_share_invitation(
State(state): State<SharedState>,
AxumPath(token): AxumPath<String>,
) -> Result<Redirect, AuthError> {
) -> Result<Json<serde_json::Value>, AuthError> {
let token_hash = hash_token(token.trim());
let row: Option<(String, String, i64, String, String, Option<String>)> = sqlx::query_as(
queries::get(state.db.kind(), queries::SHARE_INVITATION_FIND_TOKEN),
@@ -1320,7 +1319,7 @@ pub async fn accept_share_invitation(
} else {
format!("/p/{slug}")
};
Ok(Redirect::to(&target))
Ok(Json(serde_json::json!({"ok": true, "url": target})))
}
pub async fn remove_resource_user(
+24
View File
@@ -344,6 +344,11 @@ export async function handleAccountConfirmationToken() {
const token = mailActionToken("/auth/confirm", "confirm_token");
if (!token) return false;
clearMailActionUrl();
const confirmed = await askConfirm(
"Confirm activation of this RustPad account.",
{ title: "Confirm account", confirmText: "Activate account" },
);
if (!confirmed) return true;
try {
const result = await api("/api/auth/confirm-account", { method: "POST", body: JSON.stringify({ token }) });
await showMessage(result.message, { title: "Account confirmed" });
@@ -378,6 +383,25 @@ export async function handleResetToken() {
return true;
}
export async function handleShareInvitationToken() {
const token = mailActionToken("/share-invitations", "share_invitation_token");
if (!token || !location.pathname.endsWith("/accept")) return false;
clearMailActionUrl();
const confirmed = await askConfirm(
"Accept this sharing invitation?",
{ title: "Sharing invitation", confirmText: "Accept invitation" },
);
if (!confirmed) return true;
try {
const result = await api(`/share-invitations/${encodeURIComponent(token)}/accept`, { method: "POST" });
window.location.assign(result.url);
} catch (error) {
await showMessage(error.message, { title: "Invitation failed" });
}
return true;
}
export async function handleAccountActionToken() {
const token = mailActionToken("/auth/account-action", "account_action_token");
if (!token) return false;
+2 -2
View File
@@ -1,7 +1,7 @@
import { installGlobalDiagnostics, logInfo } from "@rustpad/logger";
installGlobalDiagnostics();
import { bindIdentityDialog, handleAccountActionToken, handleAccountConfirmationToken, handleResetToken, logoutCurrentSession, validateCurrentSession } from "@rustpad/auth-ui";
import { bindIdentityDialog, handleAccountActionToken, handleAccountConfirmationToken, handleResetToken, handleShareInvitationToken, logoutCurrentSession, validateCurrentSession } from "@rustpad/auth-ui";
import { getAuthToken, setAccessToken } from "@rustpad/session";
import { api } from "@rustpad/api";
import { copyText } from "@rustpad/clipboard";
@@ -83,7 +83,7 @@ document.querySelector("#workspace-form").addEventListener("submit", async (even
}
});
await handleAccountConfirmationToken() || await handleResetToken() || await handleAccountActionToken();
await handleAccountConfirmationToken() || await handleResetToken() || await handleAccountActionToken() || await handleShareInvitationToken();
const identityDialog = document.querySelector("#identity-dialog");
const guestAccount = document.querySelector("#footer-account-guest");