mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Implementing logged in password change.
This commit is contained in:
parent
140b312916
commit
54c7460fc4
8 changed files with 169 additions and 7 deletions
|
|
@ -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']
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 || [];
|
||||
|
|
|
|||
74
src/routes/(app)/(protected)/password/change/+page.server.ts
Normal file
74
src/routes/(app)/(protected)/password/change/+page.server.ts
Normal 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.');
|
||||
}
|
||||
};
|
||||
55
src/routes/(app)/(protected)/password/change/+page.svelte
Normal file
55
src/routes/(app)/(protected)/password/change/+page.svelte
Normal 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>
|
||||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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 }) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue