cleaner login and registration

This commit is contained in:
Alexander Bocken 2023-07-18 12:05:30 +02:00
parent ffa4496c16
commit 70e640aa9a
Signed by: Alexander
GPG Key ID: 1D237BE83F9B05E8
12 changed files with 153 additions and 30 deletions

28
src/hooks.server.ts Normal file
View File

@ -0,0 +1,28 @@
import { authenticateUser } from "$lib/js/authenticate"
import type { Handle } from "@sveltejs/kit"
import { redirect } from "@sveltejs/kit"
import { error } from "@sveltejs/kit"
export const handle : Handle = async({event, resolve}) => {
event.locals.user = await authenticateUser(event)
if(event.url.pathname.startsWith('/rezepte/edit') || event.url.pathname.startsWith('/rezepte/add')){
if(!event.locals.user){
throw redirect(303, "/login")
}
else if(!event.locals.user.access.includes("rezepte")){
throw error(401, "Your user does not have access to this page")
}
}
else if(event.url.pathname.startsWith('/abrechnung')){
console.log(event.locals.user)
if(!event.locals.user){
throw redirect(303, "/login")
}
else if(!event.locals.user.access.includes("abrechnung")){
throw error(401, "Your User does not have access to this page")
}
}
const response = await resolve(event)
return response
}

View File

@ -0,0 +1,40 @@
import type { RequestEvent } from "@sveltejs/kit";
import { COOKIE_SECRET } from "$env/static/private";
import { verify } from "jsonwebtoken";
import { error } from "@sveltejs/kit";
import { dbConnect, dbDisconnect } from "../../utils/db";
import { User } from "../../models/User";;
export async function authenticateUser(event: RequestEvent){
// Set your master secret key (replace with your own secret)
const { cookies } = event;
const masterSecret = COOKIE_SECRET;
const secretKey = masterSecret
let decoded
try{
const cookie : string = cookies.get("UserSession")
if(cookie){
decoded = await verify(cookie, secretKey);
}
}
catch(e){
throw error(401, "Cookies have changed, please log in again")
}
if(decoded){
await dbConnect()
let res = await User.findOne({username: decoded.username}, 'access').lean();
await dbDisconnect()
if(!res){
throw error(404, "User for this Cookie does no longer exist")
}
return {
username: decoded.username,
access: res.access
}
}
else{
return null
}
}

View File

@ -11,7 +11,6 @@ import { User } from '../../../models/User';
// recipe json in body // recipe json in body
export const POST: RequestHandler = async ({request}) => { export const POST: RequestHandler = async ({request}) => {
const {username, password} = await request.json() const {username, password} = await request.json()
// TODO: get salt from user in DB
await dbConnect() await dbConnect()
let res = await User.findOne({username: username}, 'pass_hash salt').lean() let res = await User.findOne({username: username}, 'pass_hash salt').lean()
await dbDisconnect() await dbDisconnect()
@ -31,17 +30,6 @@ export const POST: RequestHandler = async ({request}) => {
return new Response(JSON.stringify(res)) return new Response(JSON.stringify(res))
}; };
async function hashPassword(password) {
try {
const salt = await generateSalt(); // Generate a random salt
const hashedPassword = await hash(password, salt); // Hash the password with the salt
return { hashedPassword, salt };
} catch (error) {
console.error('Error hashing password:', error);
}
}
async function createJWT(username) { async function createJWT(username) {
const payload = { const payload = {
username: username, username: username,

View File

@ -49,16 +49,3 @@ async function hashPassword(password, salt) {
console.error('Error hashing password:', error); console.error('Error hashing password:', error);
} }
} }
async function createJWT(username, userSalt) {
const payload = {
username: username,
};
const masterSecret = COOKIE_SECRET;
const secretKey = masterSecret + userSalt;
const jwt = sign(payload, secretKey);
return jwt
}

View File

@ -15,7 +15,6 @@ import { getJWTFromRequest } from '../../../utils/cookie';
// recipe json in body // recipe json in body
export const GET: RequestHandler = async ({request}) => { export const GET: RequestHandler = async ({request}) => {
const jwt = getJWTFromRequest(request) const jwt = getJWTFromRequest(request)
console.log(jwt)
// Set your master secret key (replace with your own secret) // Set your master secret key (replace with your own secret)
const masterSecret = COOKIE_SECRET; const masterSecret = COOKIE_SECRET;

View File

@ -0,0 +1,32 @@
import { redirect } from "@sveltejs/kit"
import type { Actions, PageServerLoad } from "./$types"
export const load: PageServerLoad = async ({ locals }) => {
return {
user: locals.user,
}
}
export const actions: Actions = {
login: async (event) => {
const data = await event.request.formData()
const res = await event.fetch('/api/login',
{method: 'POST',
body: JSON.stringify({
username: data.get('username'),
password: data.get('password'),
})
}
)
const jwt = await res.json()
event.cookies.set("UserSession", jwt, {
path: "/",
httpOnly: true,
sameSite: "strict",
secure: process.env.NODE_ENV === "production",
maxAge: 60 * 60 * 24 * 7, // 1 week
})
throw redirect(303, "/")
},
}

View File

@ -0,0 +1,42 @@
<script>
import Header from '$lib/components/Header.svelte'
import { setCookie } from 'svelte-cookie';
export async function createJWT() {
const res = await fetch('/api/login',
{method: 'POST',
body: JSON.stringify({
username: "testuser2",
password: "password",
})
}
)
const jwt = await res.json()
setCookie('UserSession', jwt, {expires: 7})
}
</script>
<style>
</style>
<Header>
<ul class=site_header slot=links>
<li><a href="/rezepte">Rezepte</a></li>
<li><a href="/bilder">Bilder</a></li>
<li><a href="/git">Git</a></li>
<li><a href="/transmission">Transmission</a></li>
</ul>
<h1>Log In</h1>
<form action="?/login" method=POST>
<label>
Username
<input type="text" name="username">
</label>
<label>
Passwort
<input name="password" type="password">
</label>
<button type="submit">Log In</button>
</form>
</Header>

View File

@ -9,7 +9,7 @@
import IngredientsPage from '$lib/components/IngredientsPage.svelte'; import IngredientsPage from '$lib/components/IngredientsPage.svelte';
import TitleImgParallax from '$lib/components/TitleImgParallax.svelte'; import TitleImgParallax from '$lib/components/TitleImgParallax.svelte';
import { afterNavigate } from '$app/navigation'; import { afterNavigate } from '$app/navigation';
import {season} from '$lib/js/season_store'; import {season} from '$lib/js/season_store';
export let data: PageData; export let data: PageData;

View File

@ -0,0 +1 @@
{"terminal": "nvimterm"}

View File

@ -0,0 +1,5 @@
export async function load({locals}) {
return {
user: locals.user
};
};

View File

@ -1,8 +1,10 @@
import type { PageLoad } from "./$types"; import type { PageLoad } from "./$types";
export async function load({ fetch, params}) { export async function load({ fetch, params, locals}) {
let current_month = new Date().getMonth() + 1 let current_month = new Date().getMonth() + 1
const res = await fetch(`/api/items/${params.name}`); const res = await fetch(`/api/items/${params.name}`);
const recipe = await res.json(); const recipe = await res.json();
return {recipe}; return {recipe: recipe,
user: locals.user
};
}; };

View File

@ -342,7 +342,6 @@ h3{
} }
</style> </style>
<h1>Rezept editieren</h1> <h1>Rezept editieren</h1>
<CardAdd {card_data} {image_preview_url} ></CardAdd> <CardAdd {card_data} {image_preview_url} ></CardAdd>
<h3>Kurzname (für URL):</h3> <h3>Kurzname (für URL):</h3>