Extract token directly from url

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-08-21 18:46:26 +02:00
parent 39774f814d
commit bc2e0595cf
2 changed files with 31 additions and 48 deletions

View File

@@ -5,10 +5,8 @@ import { z } from "zod";
import { useFormWithSchema } from "/hooks/useFormWithSchema"; import { useFormWithSchema } from "/hooks/useFormWithSchema";
import { usePageTitle } from "@probo/hooks"; import { usePageTitle } from "@probo/hooks";
import { buildEndpoint } from "/providers/RelayProviders"; import { buildEndpoint } from "/providers/RelayProviders";
import { useEffect } from "react";
const schema = z.object({ const schema = z.object({
token: z.string(),
password: z.string().min(8), password: z.string().min(8),
}); });
@@ -16,17 +14,28 @@ export default function ConfirmInvitationPage() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const navigate = useNavigate(); const navigate = useNavigate();
const { toast } = useToast(); const { toast } = useToast();
const { register, handleSubmit, formState, setValue } = useFormWithSchema( const { register, handleSubmit, formState } = useFormWithSchema(
schema, schema,
{ {
defaultValues: { defaultValues: {
token: "",
password: "", password: "",
}, },
} }
); );
const onSubmit = handleSubmit(async (data) => { const onSubmit = handleSubmit(async (data) => {
const searchParams = new URLSearchParams(location.search);
const token = searchParams.get("token");
if (!token) {
toast({
title: __("Confirmation failed"),
description: __("Invalid or missing invitation token"),
variant: "error",
});
return;
}
const response = await fetch( const response = await fetch(
buildEndpoint("/api/console/v1/auth/invitation"), buildEndpoint("/api/console/v1/auth/invitation"),
{ {
@@ -35,7 +44,10 @@ export default function ConfirmInvitationPage() {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
credentials: "include", credentials: "include",
body: JSON.stringify(data), body: JSON.stringify({
token: token,
password: data.password,
}),
} }
); );
@@ -60,15 +72,6 @@ export default function ConfirmInvitationPage() {
usePageTitle(__("Confirm invitation")); usePageTitle(__("Confirm invitation"));
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
const urlToken = searchParams.get("token");
if (urlToken) {
setValue("token", urlToken);
}
}, [location.search, setValue]);
return ( return (
<div className="space-y-6 w-full max-w-md mx-auto"> <div className="space-y-6 w-full max-w-md mx-auto">
<div className="space-y-2 text-center"> <div className="space-y-2 text-center">
@@ -79,16 +82,6 @@ export default function ConfirmInvitationPage() {
</div> </div>
<form onSubmit={onSubmit} className="space-y-4"> <form onSubmit={onSubmit} className="space-y-4">
<Field
label={__("Token")}
type="text"
hidden
placeholder={__("Enter your token")}
{...register("token")}
required
error={formState.errors.token?.message}
/>
<Field <Field
label={__("Password")} label={__("Password")}
type="password" type="password"

View File

@@ -5,11 +5,9 @@ import { z } from "zod";
import { useFormWithSchema } from "/hooks/useFormWithSchema"; import { useFormWithSchema } from "/hooks/useFormWithSchema";
import { usePageTitle } from "@probo/hooks"; import { usePageTitle } from "@probo/hooks";
import { buildEndpoint } from "/providers/RelayProviders"; import { buildEndpoint } from "/providers/RelayProviders";
import { useEffect } from "react";
const schema = z const schema = z
.object({ .object({
token: z.string(),
password: z.string().min(8), password: z.string().min(8),
confirmPassword: z.string().min(8), confirmPassword: z.string().min(8),
}) })
@@ -22,11 +20,10 @@ export default function ResetPasswordPage() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const navigate = useNavigate(); const navigate = useNavigate();
const { toast } = useToast(); const { toast } = useToast();
const { register, handleSubmit, formState, setValue } = useFormWithSchema( const { register, handleSubmit, formState } = useFormWithSchema(
schema, schema,
{ {
defaultValues: { defaultValues: {
token: "",
password: "", password: "",
confirmPassword: "", confirmPassword: "",
}, },
@@ -34,6 +31,18 @@ export default function ResetPasswordPage() {
); );
const onSubmit = handleSubmit(async (data) => { const onSubmit = handleSubmit(async (data) => {
const searchParams = new URLSearchParams(location.search);
const token = searchParams.get("token");
if (!token) {
toast({
title: __("Reset failed"),
description: __("Invalid or missing reset token"),
variant: "error",
});
return;
}
const response = await fetch( const response = await fetch(
buildEndpoint("/api/console/v1/auth/reset-password"), buildEndpoint("/api/console/v1/auth/reset-password"),
{ {
@@ -43,7 +52,7 @@ export default function ResetPasswordPage() {
}, },
credentials: "include", credentials: "include",
body: JSON.stringify({ body: JSON.stringify({
token: data.token, token: token,
password: data.password, password: data.password,
}), }),
} }
@@ -70,15 +79,6 @@ export default function ResetPasswordPage() {
usePageTitle(__("Reset password")); usePageTitle(__("Reset password"));
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
const urlToken = searchParams.get("token");
if (urlToken) {
setValue("token", urlToken);
}
}, [location.search, setValue]);
return ( return (
<div className="space-y-6 w-full max-w-md mx-auto"> <div className="space-y-6 w-full max-w-md mx-auto">
<div className="space-y-2 text-center"> <div className="space-y-2 text-center">
@@ -89,16 +89,6 @@ export default function ResetPasswordPage() {
</div> </div>
<form onSubmit={onSubmit} className="space-y-4"> <form onSubmit={onSubmit} className="space-y-4">
<Field
label={__("Token")}
type="text"
hidden
placeholder={__("Enter your token")}
{...register("token")}
required
error={formState.errors.token?.message}
/>
<Field <Field
label={__("New Password")} label={__("New Password")}
type="password" type="password"