Browse Source

be able to change password

pull/1645/head
Bernd Storath 6 months ago
parent
commit
e0ba58d579
  1. 32
      src/app/pages/me.vue
  2. 13
      src/server/api/me/password.post.ts
  3. 30
      src/server/database/repositories/user/service.ts
  4. 13
      src/server/database/repositories/user/types.ts

32
src/app/pages/me.vue

@ -79,7 +79,7 @@ async function submit() {
message: 'Saved', message: 'Saved',
}); });
if (!res.success) { if (!res.success) {
throw new Error('Failed to save'); throw new Error('Failed to update general');
} }
await refreshNuxtData(); await refreshNuxtData();
} catch (e) { } catch (e) {
@ -98,13 +98,33 @@ const currentPassword = ref('');
const newPassword = ref(''); const newPassword = ref('');
const confirmPassword = ref(''); const confirmPassword = ref('');
function updatePassword() { async function updatePassword() {
if (newPassword.value !== confirmPassword.value) { try {
const res = await $fetch(`/api/me/password`, {
method: 'post',
body: {
currentPassword: currentPassword.value,
newPassword: newPassword.value,
confirmPassword: confirmPassword.value,
},
});
toast.showToast({ toast.showToast({
type: 'error', type: 'success',
title: 'Error', title: 'Success',
message: 'Passwords do not match', message: 'Saved',
}); });
if (!res.success) {
throw new Error('Failed to update password');
}
await refreshNuxtData();
} catch (e) {
if (e instanceof FetchError) {
toast.showToast({
type: 'error',
title: 'Error',
message: e.data.message,
});
}
} }
} }
</script> </script>

13
src/server/api/me/password.post.ts

@ -0,0 +1,13 @@
import { UserUpdatePasswordSchema } from '#db/repositories/user/types';
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event, user }) => {
const { newPassword, currentPassword } = await readValidatedBody(
event,
validateZod(UserUpdatePasswordSchema)
);
await Database.users.updatePassword(user.id, currentPassword, newPassword);
return { success: true };
}
);

30
src/server/database/repositories/user/service.ts

@ -72,4 +72,34 @@ export class UserService {
async update(id: ID, name: string, email: string | null) { async update(id: ID, name: string, email: string | null) {
return this.#statements.update.execute({ id, name, email }); return this.#statements.update.execute({ id, name, email });
} }
async updatePassword(id: ID, currentPassword: string, newPassword: string) {
const hash = await hashPassword(newPassword);
return this.#db.transaction(async (tx) => {
// get user again to avoid password changing while request
const txUser = await tx.query.user
.findFirst({ where: eq(user.id, id) })
.execute();
if (!txUser) {
throw new Error('User not found');
}
const passwordValid = await isPasswordValid(
currentPassword,
txUser.password
);
if (!passwordValid) {
throw new Error('Invalid password');
}
await tx
.update(user)
.set({ password: hash })
.where(eq(user.id, id))
.execute();
});
}
} }

13
src/server/database/repositories/user/types.ts

@ -61,3 +61,16 @@ export const UserUpdateSchema = z.object(
}, },
{ message: objectMessage } { message: objectMessage }
); );
export const UserUpdatePasswordSchema = z
.object(
{
currentPassword: password,
newPassword: password,
confirmPassword: password,
},
{ message: objectMessage }
)
.refine((val) => val.newPassword === val.confirmPassword, {
message: 'zod.user.passwordMatch',
});

Loading…
Cancel
Save