Fix password update (#71)
* Fix password update * Use next or callback params for retro-compatibility
This commit is contained in:
committed by
GitHub
parent
2fe8fc0231
commit
25adc2d1e3
@@ -80,4 +80,10 @@ export class AuthPageObject {
|
|||||||
|
|
||||||
await this.visitConfirmEmailLink(email);
|
await this.visitConfirmEmailLink(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updatePassword(password: string) {
|
||||||
|
await this.page.fill('[name="password"]', password);
|
||||||
|
await this.page.fill('[name="repeatPassword"]', password);
|
||||||
|
await this.page.click('[type="submit"]');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
48
apps/e2e/tests/authentication/password-reset.spec.ts
Normal file
48
apps/e2e/tests/authentication/password-reset.spec.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
import { AuthPageObject } from './auth.po';
|
||||||
|
|
||||||
|
const email = 'owner@makerkit.dev';
|
||||||
|
const newPassword = (Math.random() * 10000).toString();
|
||||||
|
|
||||||
|
test.describe('Password Reset Flow', () => {
|
||||||
|
test.describe.configure({ mode: 'serial' });
|
||||||
|
|
||||||
|
test('will reset the password and sign in with new one', async ({ page }) => {
|
||||||
|
const auth = new AuthPageObject(page);
|
||||||
|
|
||||||
|
await page.goto('/auth/password-reset');
|
||||||
|
|
||||||
|
await page.fill('[name="email"]', email);
|
||||||
|
await page.click('[type="submit"]');
|
||||||
|
|
||||||
|
await auth.visitConfirmEmailLink(email);
|
||||||
|
|
||||||
|
await page.waitForURL('/update-password');
|
||||||
|
|
||||||
|
await auth.updatePassword(newPassword);
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('a', {
|
||||||
|
hasText: 'Back to Home Page',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page.waitForURL('/home');
|
||||||
|
|
||||||
|
await auth.signOut();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('a', {
|
||||||
|
hasText: 'Sign in',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await auth.signIn({
|
||||||
|
email,
|
||||||
|
password: newPassword,
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.waitForURL('/home');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -15,11 +15,13 @@ export const generateMetadata = async () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Logo = () => <AppLogo href={''} />;
|
||||||
|
|
||||||
async function UpdatePasswordPage() {
|
async function UpdatePasswordPage() {
|
||||||
await requireUserInServerComponent();
|
await requireUserInServerComponent();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthLayoutShell Logo={AppLogo}>
|
<AuthLayoutShell Logo={Logo}>
|
||||||
<UpdatePasswordForm redirectTo={pathsConfig.app.home} />
|
<UpdatePasswordForm redirectTo={pathsConfig.app.home} />
|
||||||
</AuthLayoutShell>
|
</AuthLayoutShell>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { If } from '@kit/ui/if';
|
|||||||
import { Input } from '@kit/ui/input';
|
import { Input } from '@kit/ui/input';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
|
import { useCaptchaToken } from '../captcha/client';
|
||||||
import { AuthErrorAlert } from './auth-error-alert';
|
import { AuthErrorAlert } from './auth-error-alert';
|
||||||
|
|
||||||
const PasswordResetSchema = z.object({
|
const PasswordResetSchema = z.object({
|
||||||
@@ -31,6 +32,8 @@ export function PasswordResetRequestContainer(params: {
|
|||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation('auth');
|
const { t } = useTranslation('auth');
|
||||||
const resetPasswordMutation = useRequestResetPassword();
|
const resetPasswordMutation = useRequestResetPassword();
|
||||||
|
const { captchaToken, resetCaptchaToken } = useCaptchaToken();
|
||||||
|
|
||||||
const error = resetPasswordMutation.error;
|
const error = resetPasswordMutation.error;
|
||||||
const success = resetPasswordMutation.data;
|
const success = resetPasswordMutation.data;
|
||||||
|
|
||||||
@@ -55,11 +58,20 @@ export function PasswordResetRequestContainer(params: {
|
|||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
onSubmit={form.handleSubmit(({ email }) => {
|
onSubmit={form.handleSubmit(({ email }) => {
|
||||||
return resetPasswordMutation.mutateAsync({
|
const redirectTo = new URL(
|
||||||
email,
|
params.redirectPath,
|
||||||
redirectTo: new URL(params.redirectPath, window.location.origin)
|
window.location.origin,
|
||||||
.href,
|
).href;
|
||||||
});
|
|
||||||
|
return resetPasswordMutation
|
||||||
|
.mutateAsync({
|
||||||
|
email,
|
||||||
|
redirectTo,
|
||||||
|
captchaToken,
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
resetCaptchaToken();
|
||||||
|
});
|
||||||
})}
|
})}
|
||||||
className={'w-full'}
|
className={'w-full'}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ class AuthCallbackService {
|
|||||||
|
|
||||||
const token_hash = searchParams.get('token_hash');
|
const token_hash = searchParams.get('token_hash');
|
||||||
const type = searchParams.get('type') as EmailOtpType | null;
|
const type = searchParams.get('type') as EmailOtpType | null;
|
||||||
const callbackParam = searchParams.get('callback');
|
const callbackParam = searchParams.get('next') ?? searchParams.get('callback');
|
||||||
|
|
||||||
let nextPath: string | null = null;
|
let nextPath: string | null = null;
|
||||||
const callbackUrl = callbackParam ? new URL(callbackParam) : null;
|
const callbackUrl = callbackParam ? new URL(callbackParam) : null;
|
||||||
|
|
||||||
|
// if we have a callback url, we check if it has a next path
|
||||||
if (callbackUrl) {
|
if (callbackUrl) {
|
||||||
// if we have a callback url, we check if it has a next path
|
// if we have a callback url, we check if it has a next path
|
||||||
const callbackNextPath = callbackUrl.searchParams.get('next');
|
const callbackNextPath = callbackUrl.searchParams.get('next');
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ import { useMutation } from '@tanstack/react-query';
|
|||||||
|
|
||||||
import { useSupabase } from './use-supabase';
|
import { useSupabase } from './use-supabase';
|
||||||
|
|
||||||
interface Params {
|
interface RequestPasswordResetMutationParams {
|
||||||
email: string;
|
email: string;
|
||||||
redirectTo: string;
|
redirectTo: string;
|
||||||
|
captchaToken?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,11 +19,12 @@ export function useRequestResetPassword() {
|
|||||||
const client = useSupabase();
|
const client = useSupabase();
|
||||||
const mutationKey = ['auth', 'reset-password'];
|
const mutationKey = ['auth', 'reset-password'];
|
||||||
|
|
||||||
const mutationFn = async (params: Params) => {
|
const mutationFn = async (params: RequestPasswordResetMutationParams) => {
|
||||||
const { error, data } = await client.auth.resetPasswordForEmail(
|
const { error, data } = await client.auth.resetPasswordForEmail(
|
||||||
params.email,
|
params.email,
|
||||||
{
|
{
|
||||||
redirectTo: params.redirectTo,
|
redirectTo: params.redirectTo,
|
||||||
|
captchaToken: params.captchaToken,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user