change password possible

This commit is contained in:
Alexander Bocken 2023-07-23 12:21:12 +02:00
parent 82a232a20f
commit 4c198e4113
Signed by: Alexander
GPG Key ID: 1D237BE83F9B05E8
5 changed files with 102 additions and 89 deletions

View File

@ -4,47 +4,51 @@ My own homepage, bocken.org (new.bocken.org for now), built with svelte-kit.
## TODO ## TODO
### General ### General
- [] Admin user management - [ ] Admin user management
- [] upload/change pfp - [ ] upload/change pfp
- [x] registration only with minimal permissions - [x] registration only with minimal permissions
- [] logout without /logout page - [ ] logout without /logout page
- [] no DB request for every Layout change if session already got the username once - [ ] no DB request for every Layout change if session already got the username once
- [] preferences page - [ ] preferences page
- [] change password - [x] change password
- [] fail2ban integration - [ ] fail2ban integration
- [ ] dark mode
### Rezepte ### Rezepte
- [] nutrition facts - [ ] nutrition facts
- [] verify randomize arrays based on day - [ ] verify randomize arrays based on day
- [] notes for next time - [ ] notes for next time
### Abrechnungen ### Abrechnungen
- [] DB setup - [ ] DB setup
- [] create new entries - [ ] create new entries
- [] delete entries - [ ] delete entries
- [] edit entries - [ ] edit entries
- [] upload img - [ ] upload img
### Flims ### Flims
- [] Calendar layout - [ ] Calendar layout
- [] DB setup - [ ] DB setup
- [] create new entries - [ ] create new entries
- [] delete entries - [ ] delete entries
- [] edit entries - [ ] edit entries
### Glaube ### Glaube
- [] just keep it as MD rendering for now? - [ ] just keep it as MD rendering for now?
- [] DB setup - [ ] DB setup
- [] Google Speech to Text API integration? - [ ] Google Speech to Text API integration?
- [] Gebete - [ ] Gebete
### Outside of this sveltekit project but planned to run on the server as well ### Outside of this sveltekit project but planned to run on the server as well
#### E-Mail #### E-Mail
- [] emailwiz setup - [ ] emailwiz setup
- [] fail2ban - [ ] fail2ban
### Dendrite ### Dendrite
- [] setup dendrite - [ ] setup dendrite
- [] OAuth? -> Everything OAuth or OpenID? - [ ] OAuth? -> Everything OAuth or OpenID?
- [] Serve some web-frontend -> Just element? - [ ] Serve some web-frontend -> Just element?
### Gitea
- [ ] consistent theming

View File

@ -130,7 +130,7 @@ h2{
<div id=options class="speech top" hidden> <div id=options class="speech top" hidden>
<h2>{username}</h2> <h2>{username}</h2>
<ul> <ul>
<!--<li><a href="/settings">Einstellungen</a></li>--> <li><a href="/settings" >Einstellungen</a></li>
<li><a href="/logout" >Log Out</a></li> <li><a href="/logout" >Log Out</a></li>
</ul> </ul>
</div> </div>

View File

@ -10,36 +10,26 @@ export const load: PageServerLoad = async ({ locals }) => {
export const actions: Actions = { export const actions: Actions = {
change_password: async (event) => { change_password: async (event) => {
const data = await event.fetch.request.formData() console.log("Changin password")
},
login: async (event) => {
const data = await event.request.formData() const data = await event.request.formData()
const res = await event.fetch('/api/user/login', const res = await event.fetch('/api/user/change_pw',
{method: 'POST', {method: 'POST',
body: JSON.stringify({ body: JSON.stringify({
username: data.get('username'), username: data.get('username'),
password: data.get('password'), new_password: data.get('new_password'),
new_password_rep: data.get('new_password_rep'),
old_password: data.get('old_password'),
}),
headers: {
credentials: 'include',
}
}) })
} if(res.ok){
) console.log("OK response")
const jwt = await res.json() }
if(res.ok){ else{
event.cookies.set("UserSession", jwt, { const item = await res.json()
path: "/", throw error(401, item.message)
httpOnly: true, }
sameSite: "strict", }
secure: process.env.NODE_ENV === "production",
maxAge: 60 * 60 * 24 * 7, // 1 week
})
throw redirect(303, "/")
}
else{
throw error(401, jwt.message)
}
},
logout: async () => {
throw redirect(303, "/logout")
},
} }

View File

@ -1,33 +1,56 @@
<script> <script>
import {enhance} from '$app/forms';
export let data export let data
let password;
const admin = data.user?.access.includes('admin') ?? false const admin = data.user?.access.includes('admin') ?? false
import "$lib/css/form.css"
</script> </script>
<style> <style>
input:invalid + div{
display: none;
}
input:valid + div{
position: absolute;
color: green;
bottom: 0.25rem;
right: -0.25rem;
font-size: 1.5rem;
width: 1em;
height: 1em;
}
form label, form label,
form label input form label input
{ {
position: relative;
display: block; display: block;
} }
input.hide{
display:none;
}
</style> </style>
<section> <section>
<h2>Change Profile pictures</h2> <h2>Change Profile pictures</h2>
</section> </section>
<section> <section>
<h2>Change password</h2> <form action="?/change_password" method=POST use:enhance>
<form> <h2>Passwort ändern</h2>
<input type="text" bind:value={data.user.username} class=hide name="username" required>
<label> <label>
Altes Passwort: Altes Passwort:
<input type="password" > <input type="password" name="old_password" required>
</label> </label>
<label> <label>
Neues Passwort: Neues Passwort:
<input type="password" > <input type="password" name="new_password" required bind:value={password} minlength=10>
<div>✔️</div>
</label> </label>
<label> <label>
Neues Passwort wiederholen: Neues Passwort wiederholen:
<input type="password" > <input type="password" name="new_password_rep" required pattern={password}>
<div>✔️</div>
</label> </label>
<button type="submit">Ändern</button>
</form> </form>
</section> </section>

View File

@ -1,6 +1,8 @@
import type { RequestHandler } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import { hash } from 'argon2'; import { verify } from 'argon2';
import { hashPassword } from '$lib/js/hashPassword'
import {randomBytes} from 'crypto'
import { PEPPER } from '$env/static/private'; import { PEPPER } from '$env/static/private';
@ -10,31 +12,25 @@ import { dbConnect, dbDisconnect } from '../../../../utils/db';
// header: use for bearer token for now // header: use for bearer token for now
// recipe json in body // recipe json in body
export const POST: RequestHandler = async ({request}) => { export const POST: RequestHandler = async ({request}) => {
const {username, old_password, new_password} = await request.json() const {username, old_password, new_password, new_password_rep} = await request.json()
if(new_password != new_password_rep){
throw error(400, 'new passwords do not match!')
}
await dbConnect(); await dbConnect();
const salt = await User.findOne({username: username}, 'salt'); const user = await User.findOne({username: username});
const pass_hash = await hashPassword(old_password + PEPPER, salt) console.log("Found user:", user)
try{ const isMatch = await verify(user.pass_hash, old_password + PEPPER, {salt: user.salt})
await User.updateOne({ console.log("isMatch:", isMatch)
username: username, if(isMatch){
pass_hash: pass_hash, const salt = randomBytes(32).toString('hex'); // Generate a random salt
}) const pass_hash = await hashPassword(new_password + PEPPER, salt)
}catch(e){ await User.findOneAndUpdate({username: username}, {pass_hash: pass_hash, salt: salt})
await dbDisconnect(); await dbDisconnect()
throw error(400, e); return new Response(JSON.stringify({message: "Password updated successfully"}),
} {status: 200})
await dbDisconnect(); }
return new Response(JSON.stringify({message: "User added successfully"}), else{
{status: 200} await dbDisconnect();
); throw error(401, "Wrong old password")
} }
}; };
async function hashPassword(password, salt) {
try {
const hashedPassword = await hash(password, salt); // Hash the password with the salt and pepper
return hashedPassword;
} catch (error) {
console.error('Error hashing password:', error);
}
}