Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions front_end/messages/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@
"forgotPasswordLink": "Zapomenuté heslo?",
"passwordResetHeading": "Resetovat heslo",
"passwordResetDescription": "Zadejte své uživatelské jméno, a pošleme Vám e-mail pro resetování hesla.",
"passwordResetPageDescription": "Tímto ukončíte všechny své aktivní relace. Vydané API klíče zůstanou platné, dokud je nerotujete.",
"resetPasswordButton": "Resetovat heslo",
"resetPasswordEmailSentHeading": "Byl Vám zaslán e-mail k resetování hesla",
"resetPasswordEmailSent1": "Vaše žádost o resetování hesla byla úspěšně zpracována.",
Expand Down Expand Up @@ -952,6 +953,11 @@
"settingsChangeEmailAddressSuccess": "Na váš nový e-mail byla zaslána potvrzovací zpráva. Prosím, následujte odkaz uvnitř pro aktivaci.",
"emailChangeErrorMessage": "Nepodařilo se změnit e-mail",
"emailChangeSuccessMessage": "Vaše e-mailová adresa byla úspěšně změněna",
"socialAccountNoPasswordBanner": "Váš účet zatím nemá nastavené heslo. Nastavte si ho níže, abyste mohli změnit svůj e-mail nebo se přihlásit pomocí e-mailu a hesla.",
"noPasswordYet": "Zatím nemáte nastavené heslo.",
"sendSetPasswordEmail": "Nastavit heslo",
"sendSetPasswordEmailSuccess": "Odkaz pro nastavení hesla byl odeslán na váš e-mail.",
"setPasswordRequiredForEmailChange": "Před změnou e-mailu si prosím nejprve nastavte heslo.",
"backToSettings": "Zpět do Nastavení",
"choices": "Možnosti",
"choicesLockedHelp": "Možnosti lze po zahájení prognózování měnit pouze v administrátorském panelu.",
Expand Down
6 changes: 6 additions & 0 deletions front_end/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@
"forgotPasswordLink": "Forgot Password?",
"passwordResetHeading": "Password Reset",
"passwordResetDescription": "Enter your username and we'll send you an email to reset your password.",
"passwordResetPageDescription": "This will end all your active sessions. Any issued API keys remain valid until you rotate them.",
"resetPasswordButton": "Reset Password",
"resetPasswordEmailSentHeading": "Password Reset Email Sent",
"resetPasswordEmailSent1": "Your password reset request has been successfully processed.",
Expand Down Expand Up @@ -906,6 +907,11 @@
"settingsChangeEmailAddressSuccess": "A confirmation email has been sent to your new address. Please follow the link inside to activate it.",
"emailChangeErrorMessage": "Failed to change email",
"emailChangeSuccessMessage": "Your email address has been changed successfully",
"socialAccountNoPasswordBanner": "Your account doesn't have a password yet. Set one below to change your email or log in with email and password.",
"noPasswordYet": "You don't have a password yet.",
"sendSetPasswordEmail": "Set password",
"sendSetPasswordEmailSuccess": "Password setup link has been sent to your email.",
"setPasswordRequiredForEmailChange": "Please set a password first before changing your email.",
"backToSettings": "Back to Settings",
"settingsMentionsInComments": "Mentions in comments",
"settingsQuestionResolution": "Resolved Questions",
Expand Down
6 changes: 6 additions & 0 deletions front_end/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@
"forgotPasswordLink": "¿Olvidaste tu contraseña?",
"passwordResetHeading": "Restablecer Contraseña",
"passwordResetDescription": "Ingresa tu nombre de usuario y te enviaremos un correo para restablecer tu contraseña.",
"passwordResetPageDescription": "Esto cerrará todas tus sesiones activas. Las claves API emitidas seguirán siendo válidas hasta que las rotas.",
"resetPasswordButton": "Restablecer Contraseña",
"resetPasswordEmailSentHeading": "Correo de Restablecimiento de Contraseña Enviado",
"resetPasswordEmailSent1": "Tu solicitud de restablecimiento de contraseña ha sido procesada con éxito.",
Expand Down Expand Up @@ -963,6 +964,11 @@
"settingsChangeEmailAddressSuccess": "Se ha enviado un correo electrónico de confirmación a tu nueva dirección. Por favor, sigue el enlace dentro para activarlo.",
"emailChangeErrorMessage": "Error al cambiar el correo electrónico",
"emailChangeSuccessMessage": "Tu dirección de correo electrónico ha sido cambiada exitosamente",
"socialAccountNoPasswordBanner": "Tu cuenta aún no tiene contraseña. Establece una a continuación para cambiar tu correo electrónico o iniciar sesión con correo y contraseña.",
"noPasswordYet": "Aún no tienes una contraseña.",
"sendSetPasswordEmail": "Establecer contraseña",
"sendSetPasswordEmailSuccess": "Se ha enviado un enlace para establecer tu contraseña a tu correo electrónico.",
"setPasswordRequiredForEmailChange": "Por favor, establece una contraseña primero antes de cambiar tu correo electrónico.",
"backToSettings": "Volver a Configuración",
"choices": "Opciones",
"inCommunityReviewStatus1": "Esta pregunta necesita aprobación de un curador de la Comunidad como tú. También puedes hacer ediciones, etiquetar al autor en un comentario a continuación, enviar la pregunta de vuelta a Borradores para revisión o rechazar la pregunta. Algunas sugerencias para preguntas de alta calidad:",
Expand Down
6 changes: 6 additions & 0 deletions front_end/messages/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
"forgotPasswordLink": "Esqueceu a Senha?",
"passwordResetHeading": "Redefinição de Senha",
"passwordResetDescription": "Insira seu nome de usuário e enviaremos um e-mail para redefinir sua senha.",
"passwordResetPageDescription": "Isso encerrará todas as suas sessões ativas. As chaves de API emitidas permanecerão válidas até que você as rotacione.",
"resetPasswordButton": "Redefinir Senha",
"resetPasswordEmailSentHeading": "E-mail de Redefinição de Senha Enviado",
"resetPasswordEmailSent1": "Sua solicitação de redefinição de senha foi processada com sucesso.",
Expand Down Expand Up @@ -725,6 +726,11 @@
"settingsChangeEmailAddressSuccess": "Um e-mail de confirmação foi enviado para seu novo endereço. Por favor, siga o link dentro para ativá-lo.",
"emailChangeErrorMessage": "Falha ao alterar o e-mail",
"emailChangeSuccessMessage": "Seu endereço de e-mail foi alterado com sucesso",
"socialAccountNoPasswordBanner": "Sua conta ainda não tem uma senha. Defina uma abaixo para alterar seu e-mail ou fazer login com e-mail e senha.",
"noPasswordYet": "Você ainda não tem uma senha.",
"sendSetPasswordEmail": "Definir senha",
"sendSetPasswordEmailSuccess": "Um link para definir sua senha foi enviado para seu e-mail.",
"setPasswordRequiredForEmailChange": "Por favor, defina uma senha primeiro antes de alterar seu e-mail.",
"backToSettings": "Voltar para Configurações",
"settingsMentionsInComments": "Menções em comentários",
"settingsQuestionResolution": "Perguntas Resolvidas",
Expand Down
6 changes: 6 additions & 0 deletions front_end/messages/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@
"forgotPasswordLink": "忘記密碼?",
"passwordResetHeading": "重設密碼",
"passwordResetDescription": "輸入您的用戶名,我們將向您發送電子郵件以重設密碼。",
"passwordResetPageDescription": "此操作將結束您所有的活躍工作階段。已發行的 API 金鑰在您輪換之前仍然有效。",
"resetPasswordButton": "重設密碼",
"resetPasswordEmailSentHeading": "重設密碼郵件已發送",
"resetPasswordEmailSent1": "您的重設密碼請求已成功處理。",
Expand Down Expand Up @@ -777,6 +778,11 @@
"settingsChangeEmailAddressSuccess": "確認信已發送到您的新地址。請循信內的鏈接以激活。",
"emailChangeErrorMessage": "更改電子郵件失敗",
"emailChangeSuccessMessage": "您的電子郵件地址已成功更改",
"socialAccountNoPasswordBanner": "您的帳號尚未設定密碼。請在下方設定密碼,以便更改電子郵件或使用電子郵件和密碼登入。",
"noPasswordYet": "您尚未設定密碼。",
"sendSetPasswordEmail": "設定密碼",
"sendSetPasswordEmailSuccess": "密碼設定連結已傳送到您的電子郵件。",
"setPasswordRequiredForEmailChange": "請先設定密碼,然後再更改電子郵件。",
"backToSettings": "返回設定",
"settingsMentionsInComments": "評論中的提及",
"settingsQuestionResolution": "已解析的問題",
Expand Down
6 changes: 6 additions & 0 deletions front_end/messages/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@
"forgotPasswordLink": "忘記密碼?",
"passwordResetHeading": "重置密碼",
"passwordResetDescription": "輸入你的用戶名,我們會向的電子郵件發送一封重置密碼的郵件。",
"passwordResetPageDescription": "此操作将结束您所有的活跃会话。已发行的 API 密钥在您轮换之前仍然有效。",
"resetPasswordButton": "重置密碼",
"resetPasswordEmailSentHeading": "重置密碼的郵件已發送",
"resetPasswordEmailSent1": "你的重置密碼請求已成功處理。",
Expand Down Expand Up @@ -954,6 +955,11 @@
"settingsChangeEmailAddressSuccess": "确认邮件已发送到您的新地址。请按照邮件中的链接激活。",
"emailChangeErrorMessage": "更改邮箱失败",
"emailChangeSuccessMessage": "您的邮箱地址已成功更改",
"socialAccountNoPasswordBanner": "您的账号尚未设置密码。请在下方设置密码,以便更改邮箱或使用邮箱和密码登录。",
"noPasswordYet": "您尚未设置密码。",
"sendSetPasswordEmail": "设置密码",
"sendSetPasswordEmailSuccess": "密码设置链接已发送到您的邮箱。",
"setPasswordRequiredForEmailChange": "请先设置密码,然后再更改邮箱。",
"backToSettings": "返回设置",
"choices": "选择",
"inCommunityReviewStatus1": "此问题需要您这样社区策展人的批准。您还可以进行编辑、在下面的评论中标记作者、将问题发送回草稿以供修改或驳回此问题。高质量问题的一些建议:",
Expand Down
8 changes: 4 additions & 4 deletions front_end/src/app/(main)/accounts/reset/actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"use server";

import { redirect } from "next/navigation";

import {
passwordResetConfirmSchema,
passwordResetRequestSchema,
Expand Down Expand Up @@ -68,13 +70,11 @@ export async function passwordResetConfirmAction(

const authManager = await getAuthCookieManager();
authManager.setAuthTokens(response.tokens);

return {
data: response,
};
} catch (err) {
return {
errors: ApiError.isApiError(err) ? err.data : undefined,
};
}

redirect("/accounts/settings/account/");
}
105 changes: 36 additions & 69 deletions front_end/src/app/(main)/accounts/reset/components/password_reset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from "@/app/(main)/accounts/schemas";
import Button from "@/components/ui/button";
import { FormError, Input } from "@/components/ui/form_field";
import LoadingSpinner from "@/components/ui/loading_spiner";

export type PasswordResetProps = {
user_id: number;
Expand All @@ -26,81 +27,47 @@ const PasswordReset: FC<PasswordResetProps> = ({ user_id, token }) => {
const { register } = useForm<PasswordResetConfirmSchema>({
resolver: zodResolver(passwordResetConfirmSchema),
});
const [state, formAction] = useActionState<
const [state, formAction, isPending] = useActionState<
PasswordResetConfirmActionState,
FormData
>(passwordResetConfirmAction, null);

return (
<>
<hr className="my-0" />
<div className="flex items-center justify-between">
<h2 className="my-4 text-2xl font-bold">{t("passwordResetHeading")}</h2>
</div>
<div>
<form
className="flex w-full flex-col gap-2 pb-4 text-sm"
action={formAction}
>
<input
type="hidden"
defaultValue={user_id}
{...register("user_id")}
<div className="mt-6 grid md:grid-cols-2">
<form className="flex flex-col gap-4" action={formAction}>
<input type="hidden" defaultValue={user_id} {...register("user_id")} />
<input type="hidden" defaultValue={token} {...register("token")} />
<div>
<Input
className="block w-full rounded border border-gray-700 bg-inherit px-3 py-2 dark:border-gray-700-dark"
placeholder={t("newPasswordPlaceholder")}
type="password"
{...register("password")}
/>
<input type="hidden" defaultValue={token} {...register("token")} />
<div>
<div className="flex w-full items-center">
<span className="w-[45%] pr-6 text-right">
{t("newPasswordLabel")}
</span>
<div className="w-full max-w-44 justify-start">
<Input
type="password"
className="w-full rounded border border-gray-500 text-base dark:border-gray-500-dark dark:bg-blue-50-dark"
{...register("password")}
/>
</div>
</div>
<div className="ml-[45%] w-full">
<FormError errors={state?.errors} name="password" />
</div>
</div>
<div>
<div className="flex w-full items-center">
<span className="w-[45%] pr-6 text-right">
{t("verifyPasswordLabel")}
</span>
<div className="w-full max-w-44 justify-start">
<Input
type="password"
className="w-full rounded border border-gray-500 text-base dark:border-gray-500-dark dark:bg-blue-50-dark"
{...register("passwordAgain")}
/>
</div>
</div>
<div className="ml-[45%] w-full">
<FormError errors={state?.errors} name="passwordAgain" />
{/* Global errors container */}
<FormError
errors={state?.errors}
name="non_field_errors"
className="text-red-500-dark"
/>
</div>
</div>
<div className="mt-4">
<Button
variant="secondary"
type="submit"
value="Submit"
className="ml-[45%] w-full max-w-44"
>
{t("changePasswordButton")}
</Button>
</div>
</form>
</div>
</>
<FormError errors={state?.errors} name="password" />
</div>
<div>
<Input
className="block w-full rounded border border-gray-700 bg-inherit px-3 py-2 dark:border-gray-700-dark"
placeholder={t("verifyPasswordPlaceholder")}
type="password"
{...register("passwordAgain")}
/>
<FormError errors={state?.errors} name="passwordAgain" />
<FormError
errors={state?.errors}
name="non_field_errors"
className="text-red-500-dark"
/>
</div>
<div className="flex items-center">
<Button variant="secondary" type="submit" disabled={isPending}>
{t("changePasswordButton")}
</Button>
{isPending && <LoadingSpinner className="ml-2" size="1x" />}
</div>
</form>
</div>
);
};

Expand Down
20 changes: 12 additions & 8 deletions front_end/src/app/(main)/accounts/reset/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import { redirect } from "next/navigation";
import { getTranslations } from "next-intl/server";

import PasswordReset from "@/app/(main)/accounts/reset/components/password_reset";
import { GlobalErrorContainer } from "@/components/global_error_boundary";
import ServerAuthApi from "@/services/api/auth/auth.server";
import { getAuthCookieManager } from "@/services/auth_tokens";
import { ApiError, logError } from "@/utils/core/errors";

export default async function ResetPassword(props: {
searchParams: Promise<{ user_id: number; token: string }>;
}) {
const searchParams = await props.searchParams;
const t = await getTranslations();

const { user_id, token } = searchParams;

const authManager = await getAuthCookieManager();
if (authManager.hasAuthSession()) {
return redirect("/");
}

try {
await ServerAuthApi.passwordResetVerifyToken(user_id, token);
} catch (error) {
Expand All @@ -27,7 +22,16 @@ export default async function ResetPassword(props: {
}

return (
<main className="mx-auto mb-24 mt-12 flex w-full max-w-3xl flex-1 flex-col bg-gray-0 p-4 text-base text-gray-800 dark:bg-blue-900 dark:text-gray-800-dark xs:p-8">
<main className="mx-auto min-h-min w-full max-w-3xl flex-auto rounded bg-gray-0 px-4 py-6 dark:bg-gray-0-dark sm:p-8 lg:my-8">
<div className="flex flex-col gap-3">
<h1 className="m-0 text-blue-800 dark:text-blue-800-dark">
{t("passwordResetHeading")}
</h1>
<div className="text-sm text-gray-600 dark:text-gray-600-dark">
{t("passwordResetPageDescription")}
</div>
</div>

<PasswordReset user_id={user_id} token={token} />
</main>
);
Expand Down
Loading
Loading