Implementing logged in password change.

This commit is contained in:
Bradley Shellnut 2023-09-20 12:46:32 +12:00
parent 140b312916
commit 54c7460fc4
8 changed files with 169 additions and 7 deletions

View file

@ -90,3 +90,31 @@ export const updateUserPasswordSchema = userSchema
});
}
});
export const changeUserPasswordSchema = z
.object({
current_password: z.string({ required_error: 'Current Password is required' }),
password: z
.string({ required_error: 'Password is required' })
.trim()
.min(8, { message: 'Password must be at least 8 characters' })
.max(128, { message: 'Password must be less than 128 characters' }),
confirm_password: z
.string({ required_error: 'Confirm Password is required' })
.trim()
.min(8, { message: 'Confirm Password must be at least 8 characters' })
})
.superRefine(({ confirm_password, password }, ctx) => {
if (confirm_password !== password) {
ctx.addIssue({
code: 'custom',
message: 'Password and Confirm Password must match',
path: ['password']
});
ctx.addIssue({
code: 'custom',
message: 'Password and Confirm Password must match',
path: ['confirm_password']
});
}
});

View file

@ -1,5 +1,5 @@
<script lang="ts">
import Transition from '$lib/components/transition/index.svelte';
import Transition from '$components/transition.svelte';
export let data;
const wishlists = data.wishlists || [];

View file

@ -0,0 +1,74 @@
import { fail, redirect } from '@sveltejs/kit';
import { message, setError, superValidate } from 'sveltekit-superforms/server';
import { changeUserPasswordSchema } from '$lib/config/zod-schemas.js';
import { auth } from '$lib/server/lucia.js';
export const load = async (event) => {
const form = await superValidate(event, changeUserPasswordSchema);
const session = await event.locals.auth.validate();
if (!session) {
throw redirect(302, '/login');
}
const { user } = session;
form.data = {
current_password: '',
password: '',
confirm_password: ''
};
return {
form
};
};
export const actions = {
default: async (event) => {
const form = await superValidate(event, changeUserPasswordSchema);
//console.log(form);
if (!form.valid) {
return fail(400, {
form
});
}
//add user to db
try {
console.log('updating profile');
const session = await event.locals.auth.validate();
if (!session) {
throw redirect(302, '/login');
}
const user = session.user;
if (user?.username) {
if (form.data.password !== form.data.confirm_password) {
return setError(form, 'Password and confirm password do not match');
}
await auth.useKey('username', user.username, form.data.current_password);
await auth.updateKeyPassword('username', user.username, form.data.password);
} else {
return setError(
form,
'Error occurred. Please try again or contact support if you need further help.'
);
}
} catch (e) {
console.error(e);
form.data.password = '';
form.data.confirm_password = '';
form.data.current_password = '';
return setError(form, 'current_password', 'Your password is incorrect.');
}
// TODO: Add toast instead?
form.data.password = '';
form.data.confirm_password = '';
form.data.current_password = '';
return message(form, 'Profile updated successfully.');
}
};

View file

@ -0,0 +1,55 @@
<script lang="ts">
import { superForm } from 'sveltekit-superforms/client';
//import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte';
import { changeUserPasswordSchema, userSchema } from '$lib/config/zod-schemas';
import { AlertTriangle, KeyRound } from 'lucide-svelte';
import { Label } from '$components/ui/label';
import { Input } from '$components/ui/input';
import { Button } from '$components/ui/button';
export let data;
const { form, errors, enhance, delayed, message } = superForm(data.form, {
taintedMessage: null,
validators: changeUserPasswordSchema,
delayMs: 0
});
</script>
<form method="POST" use:enhance>
<!--<SuperDebug data={$form} />-->
<h3>Change Password</h3>
<hr class="!border-t-2 mt-2 mb-6" />
{#if $message}
<aside class="alert variant-filled-success mt-6">
<!-- Message -->
<div class="alert-message">
<p>{$message}</p>
</div>
</aside>
{/if}
<div class="mt-6">
<Label for="current_password">Current Password</Label>
<Input type="password" id="current_password" name="current_password" placeholder="Current Password" autocomplete="password" data-invalid={$errors.current_password} bind:value={$form.current_password} />
{#if $errors.current_password}
<small>{$errors.current_password}</small>
{/if}
</div>
<div class="mt-6">
<Label for="password">New Password</Label>
<Input type="password" id="password" name="password" placeholder="Password" autocomplete="given-name" data-invalid={$errors.password} bind:value={$form.password} />
{#if $errors.password}
<small>{$errors.password}</small>
{/if}
</div>
<div class="mt-6">
<Label for="confirm_password">Confirm New Password</Label>
<Input type="password" id="confirm_password" name="confirm_password" placeholder="Confirm Password" autocomplete="family-name" data-invalid={$errors.confirm_password} bind:value={$form.confirm_password} />
{#if $errors.confirm_password}
<small>{$errors.confirm_password}</small>
{/if}
</div>
<div class="mt-6">
<Button type="submit" class="w-full">Change Password</Button>
</div>
</form>

View file

@ -2,7 +2,7 @@
import { superForm } from 'sveltekit-superforms/client';
//import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte';
import { userSchema } from '$lib/config/zod-schemas';
import { AlertTriangle } from 'lucide-svelte';
import { AlertTriangle, KeyRound } from 'lucide-svelte';
import { Label } from '$components/ui/label';
import { Input } from '$components/ui/input';
import { Button } from '$components/ui/button';
@ -63,8 +63,10 @@
{/if}
</div>
<div class="mt-6">
<Button variant="link" href="/password/reset">Change Password</Button>
<!-- <a href="/password/reset">Change Password</a> -->
<Button variant="link" class="text-secondary-foreground" href="/password/change">
<KeyRound class="mr-2 h-4 w-4" />
Change Password
</Button>
</div>
<div class="mt-6">

View file

@ -1,5 +1,7 @@
<script lang="ts">
import { page } from '$app/stores';
import { slide } from 'svelte/transition';
import { quintIn } from 'svelte/easing';
import { superForm } from 'sveltekit-superforms/client';
import * as flashModule from 'sveltekit-flash-message/client';
import toast from 'svelte-french-toast';
@ -10,12 +12,13 @@
import { signUpSchema } from '$lib/config/zod-schemas.js';
import * as Collapsible from '$lib/components/ui/collapsible';
import * as Alert from '$lib/components/ui/alert';
import { slide } from 'svelte/transition';
import { quintIn } from 'svelte/easing';
import { boredState } from '$lib/stores/boredState.js';
export let data;
const { form, errors, constraints, enhance, delayed } = superForm(data.form, {
const { form, errors, enhance } = superForm(data.form, {
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
flashMessage: {
module: flashModule,
onError: ({ result, message }) => {