initial OIDC setup

This commit is contained in:
Alexander Bocken 2024-02-14 16:07:55 +01:00
parent 1929189187
commit a781be8d00
Signed by: Alexander
GPG Key ID: 1D237BE83F9B05E8
28 changed files with 226 additions and 373 deletions

141
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "sk-recipes-test", "name": "sk-recipes-test",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@auth/sveltekit": "^0.12.3",
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/adapter-node": "^1.3.1",
"argon2": "^0.30.3", "argon2": "^0.30.3",
"cheerio": "1.0.0-rc.12", "cheerio": "1.0.0-rc.12",
@ -28,6 +29,62 @@
"vite": "^4.4.4" "vite": "^4.4.4"
} }
}, },
"node_modules/@auth/core": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/@auth/core/-/core-0.26.3.tgz",
"integrity": "sha512-Ka6rMjWMdiQCvLW/CnYZxj4Rq2bhQ/ZtU32NLxmtyAaixGb0mRXQ9MxJUBZA7GHovbghdzu55p2Cb54qNlVFzw==",
"dependencies": {
"@panva/hkdf": "^1.1.1",
"@types/cookie": "0.6.0",
"cookie": "0.6.0",
"jose": "^5.1.3",
"oauth4webapi": "^2.4.0",
"preact": "10.11.3",
"preact-render-to-string": "5.2.3"
},
"peerDependencies": {
"@simplewebauthn/browser": "^9.0.1",
"@simplewebauthn/server": "^9.0.1",
"nodemailer": "^6.8.0"
},
"peerDependenciesMeta": {
"@simplewebauthn/browser": {
"optional": true
},
"@simplewebauthn/server": {
"optional": true
},
"nodemailer": {
"optional": true
}
}
},
"node_modules/@auth/core/node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
},
"node_modules/@auth/core/node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@auth/sveltekit": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/@auth/sveltekit/-/sveltekit-0.12.3.tgz",
"integrity": "sha512-ZZhLPTkLBccJbBPom6n1ARqMNGpSO55ZJUiWhAqY8jPW+K3DtVOd4e/Je+e7g2NJ7vaDoQI4uI0V+jLDBp4B9g==",
"dependencies": {
"@auth/core": "0.26.3",
"set-cookie-parser": "^2.6.0"
},
"peerDependencies": {
"@sveltejs/kit": "^1.0.0 || ^2.0.0",
"svelte": "^3.54.0 || ^4.0.0 || ^5"
}
},
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.18.20", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@ -453,6 +510,14 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@panva/hkdf": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.1.1.tgz",
"integrity": "sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/@phc/format": { "node_modules/@phc/format": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz",
@ -1553,10 +1618,17 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
}, },
"node_modules/ip": { "node_modules/ip-address": {
"version": "2.0.0", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
}, },
"node_modules/is-arrayish": { "node_modules/is-arrayish": {
"version": "0.3.2", "version": "0.3.2",
@ -1651,6 +1723,19 @@
"@types/estree": "*" "@types/estree": "*"
} }
}, },
"node_modules/jose": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/jose/-/jose-5.2.2.tgz",
"integrity": "sha512-/WByRr4jDcsKlvMd1dRJnPfS1GVO3WuKyaurJ/vvXcOaUQO8rnNObCQMlv/5uCceVQIq5Q4WLF44ohsdiTohdg==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/jsonwebtoken": { "node_modules/jsonwebtoken": {
"version": "9.0.2", "version": "9.0.2",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
@ -2137,6 +2222,14 @@
"url": "https://github.com/fb55/nth-check?sponsor=1" "url": "https://github.com/fb55/nth-check?sponsor=1"
} }
}, },
"node_modules/oauth4webapi": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.10.3.tgz",
"integrity": "sha512-9FkXEXfzVKzH63GUOZz1zMr3wBaICSzk6DLXx+CGdrQ10ItNk2ePWzYYc1fdmKq1ayGFb2aX97sRCoZ2s0mkDw==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/object-assign": { "node_modules/object-assign": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -2244,6 +2337,26 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/preact": {
"version": "10.11.3",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz",
"integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/preact-render-to-string": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz",
"integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==",
"dependencies": {
"pretty-format": "^3.8.0"
},
"peerDependencies": {
"preact": ">=10"
}
},
"node_modules/prebuild-install": { "node_modules/prebuild-install": {
"version": "7.1.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
@ -2300,6 +2413,11 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/pretty-format": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz",
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
},
"node_modules/pump": { "node_modules/pump": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@ -2746,15 +2864,15 @@
} }
}, },
"node_modules/socks": { "node_modules/socks": {
"version": "2.7.1", "version": "2.7.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.3.tgz",
"integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "integrity": "sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw==",
"dependencies": { "dependencies": {
"ip": "^2.0.0", "ip-address": "^9.0.5",
"smart-buffer": "^4.2.0" "smart-buffer": "^4.2.0"
}, },
"engines": { "engines": {
"node": ">= 10.13.0", "node": ">= 10.0.0",
"npm": ">= 3.0.0" "npm": ">= 3.0.0"
} }
}, },
@ -2790,6 +2908,11 @@
"memory-pager": "^1.0.2" "memory-pager": "^1.0.2"
} }
}, },
"node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
},
"node_modules/streamx": { "node_modules/streamx": {
"version": "2.15.6", "version": "2.15.6",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.6.tgz", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.6.tgz",

View File

@ -21,6 +21,7 @@
"vite": "^4.4.4" "vite": "^4.4.4"
}, },
"dependencies": { "dependencies": {
"@auth/sveltekit": "^0.12.3",
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/adapter-node": "^1.3.1",
"argon2": "^0.30.3", "argon2": "^0.30.3",
"cheerio": "1.0.0-rc.12", "cheerio": "1.0.0-rc.12",

12
src/auth.ts Normal file
View File

@ -0,0 +1,12 @@
import { SvelteKitAuth } from "@auth/sveltekit"
import Authentik from "@auth/core/providers/authentik"
import { AUTHENTIK_ID, AUTHENTIK_SECRET, AUTHENTIK_ISSUER } from "$env/static/private";
export const { handle, signIn, signOut } = SvelteKitAuth({
providers: [
Authentik({
clientId: AUTHENTIK_ID,
clientSecret: AUTHENTIK_SECRET,
issuer: AUTHENTIK_ISSUER,
})],
})

View File

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

View File

@ -130,11 +130,11 @@ 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="https://sso.bocken.org/if/user/#/settings" >Einstellungen</a></li>
<li><a href="/logout" >Log Out</a></li> <li><a href="/auth/signout" >Log Out</a></li>
</ul> </ul>
</div> </div>
</button> </button>
{:else} {:else}
<a class=entry href=/login>Log In</a> <a class=entry href=/auth/signin>Log In</a>
{/if} {/if}

View File

@ -1,15 +0,0 @@
import mongoose from 'mongoose';
const PaymentSchema= new mongoose.Schema(
{
payee: {type: String, required: true},
amount: {type: Number, required: true},
for_self: {type: Number},
for_other: {type: Number},
description: {type: String},
added_by: {type: String},
date: {type: Date, required: true, default: Date.now},
}, {timestamps: true}
);
export const Payment = mongoose.model("Payment", PaymentSchema);

View File

@ -2,6 +2,8 @@ import { get_username } from '$lib/js/get_username';;
import type { Actions, PageServerLoad } from "./$types" import type { Actions, PageServerLoad } from "./$types"
import { error } from "@sveltejs/kit" import { error } from "@sveltejs/kit"
export const load = (async ({cookies}) => { export const load = (async ({cookies, locals}) => {
return { user: await get_username(cookies) } return {
session: await locals.auth(),
}
}); });

View File

@ -3,9 +3,10 @@ import Header from '$lib/components/Header.svelte'
import UserHeader from '$lib/components/UserHeader.svelte'; import UserHeader from '$lib/components/UserHeader.svelte';
export let data export let data
let username = "" let username = ""
if(data.user){ if(data.session){
username = data.user.username username = data.session.user.name
} }
console.log(data)
</script> </script>
<Header> <Header>

View File

@ -2,6 +2,10 @@
import "$lib/css/nordtheme.css"; import "$lib/css/nordtheme.css";
import LinksGrid from "$lib/components/LinksGrid.svelte"; import LinksGrid from "$lib/components/LinksGrid.svelte";
export let data; export let data;
import { SignIn, SignOut } from "@auth/sveltekit/components"
import { page } from "$app/stores"
/*console.log($page)*/
/*console.log($page.daja.session.user)*/
</script> </script>
<style> <style>
.hero{ .hero{
@ -49,7 +53,8 @@ section h2{
} }
</style> </style>
{#if ! data.user} {#if ! data.session}
<section class=hero> <section class=hero>
<img src="https://bocken.org/static/user/full/Alexander.webp" alt="Smiling Alexander Bocken"> <img src="https://bocken.org/static/user/full/Alexander.webp" alt="Smiling Alexander Bocken">
<div> <div>

View File

@ -1,35 +0,0 @@
import { redirect } from "@sveltejs/kit"
import type { Actions, PageServerLoad } from "./$types"
import { error } from "@sveltejs/kit"
export const actions: Actions = {
login: async (event) => {
const data = await event.request.formData()
const res = await event.fetch('/api/user/login',
{method: 'POST',
body: JSON.stringify({
username: data.get('username'),
password: data.get('password'),
})
}
)
const jwt = await res.json()
if(res.ok){
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, "/")
}
else{
throw error(401, jwt.message)
}
},
logout: async () => {
throw redirect(303, "/logout")
},
}

View File

@ -1,23 +0,0 @@
<script>
import "$lib/css/form.css"
import "$lib/css/nordtheme.css"
</script>
<form action="?/login" method=POST>
<h1>Log In</h1>
<p>
Note: This is a separate account to all the services running on this server.
Please only use this login if you want to edit recipes.
In the future, this login will be merged with the other services.
</p>
<label>
Benutzername
<input type="text" name="username" required>
</label>
<label>
Passwort
<input name="password" type="password" required>
</label>
<button type="submit">Log In</button>
<p>Noch keinen Account? <a href=/register>Hier registrieren</a>.</p>
</form>

View File

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

View File

@ -1,8 +0,0 @@
import redirect from "@sveltejs/kit"
import type { Actions } from './$types';
export const actions: Actions = {
default: async ({cookies}) => {
cookies.delete("UserSession")
}
} satisfies Actions;

View File

@ -1,7 +0,0 @@
<script>
import "$lib/css/form.css"
</script>
<form method='POST'>
<h1>Log out</h1>
<button type='submit'>Log Out</button>
</form>

View File

@ -1,61 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { Payment } from '../../../../models/Payment';
import { dbConnect, dbDisconnect } from '../../../../utils/db';
import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';;
import sharp from 'sharp';
import path from 'path';
import {IMAGE_DIR} from '$env/static/private';
export const POST: RequestHandler = async ({request, cookies}) => {
const user = await authenticateUser(cookies)
if(!user){
throw error(401, "Not logged in")
}
if(!user.access.includes("abrechnung")){
throw error(401, "This user does not have permissions to add payments")
}
else{
const formData = await request.formData();
const json = {
amount: formData.get("amount"),
for_self: formData.get("for_self"),
for_other: formData.get("for_other"),
payee: formData.get("payee"),
added_by: user._id
}
await dbConnect();
let id;
try{
id = (await Payment.create(json))._id.toString();
} catch(e){
await dbDisconnect();
throw error(400, e)
}
await dbDisconnect();
const img = formData.get("file")
if(img){
//this feels stupid, is there a smarter way directly to Buffer?
const full_res = Buffer.from(await img.arrayBuffer())
await sharp(full_res)
.toFormat('webp')
.toFile(path.join(IMAGE_DIR,
"abrechnung",
"full",
id + '.webp'))
await sharp(full_res)
.resize({width: 20})
.toFormat('webp')
.toFile(path.join(IMAGE_DIR,
"abrechnung",
"placeholder",
id + '.webp'))
}
return new Response(JSON.stringify({message: "Added payment successfully"}),{
status: 200,
});
}
};

View File

@ -1,24 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { Payment } from '../../../../models/Payment';
import { dbConnect, dbDisconnect } from '../../../../utils/db';
import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
// header: use for bearer token for now
// recipe json in body
export const POST: RequestHandler = async ({request, cookies}) => {
let json = await request.json()
const user = await authenticateUser(cookies)
if(!user) throw error(401, "Need to be logged in")
if(!user.access.includes("abrechnung")){
throw error(401, "Insufficient permissions")
}
else{
await dbConnect();
await Payment.findOneAndDelete({_id: json.id});
await dbDisconnect();
return new Response(JSON.stringify({msg: "Deleted payment successfully"}),{
status: 200,
});
}
}

View File

@ -1,27 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { Payment } from '../../../../models/Payment';
import { dbConnect, dbDisconnect } from '../../../../utils/db';
import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
// header: use for bearer token for now
// recipe json in body
export const POST: RequestHandler = async ({request, cookies}) => {
let message = await request.json()
const json = message.payment
const user = await authenticateUser(cookies)
if(!user){
throw error(403, "Not logged in")
}
else if(!user.access.includes("abrechnung")){
throw error(403, "This user does not have edit permissions for payments")
}
else{
await dbConnect();
await Payment.findOneAndUpdate({_id: json.id}, json);
await dbDisconnect();
return new Response(JSON.stringify({msg: "Edited payment successfully"}),{
status: 200,
});
}
};

View File

@ -1,27 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { Payment } from '../../../../../models/Payment';
import { dbConnect, dbDisconnect } from '../../../../../utils/db';
import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
// header: use for bearer token for now
// recipe json in body
export const POST: RequestHandler = async ({request, cookies}) => {
let message = await request.json()
const json = message.payment
const user = await authenticateUser(cookies)
if(!user){
throw error(403, "Not logged in")
}
else if(!user.access.includes("abrechnung")){
throw error(403, "This user does not have edit permissions for payments")
}
else{
await dbConnect();
const payment = await Payment.findOne({_id: json.id}).lean();
await dbDisconnect();
return new Response(JSON.stringify({payment}),{
status: 200,
});
}
};

View File

@ -1,28 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { Payment } from '../../../../../models/Payment';
import { dbConnect, dbDisconnect } from '../../../../../utils/db';
import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
// header: use for bearer token for now
// recipe json in body
export const POST: RequestHandler = async ({request, cookies, params}) => {
let message = await request.json()
const n = params.range
const start = message?.start ?? 0;
const user = await authenticateUser(cookies)
if(!user){
throw error(403, "Not logged in")
}
else if(!user.access.includes("abrechnung")){
throw error(403, "This user does not have viewing permissions for payments")
}
else{
await dbConnect();
const payments = await Payment.find({}).sort({ date: -1 }).skip(start).limit(n).lean()
await dbDisconnect();
return new Response(JSON.stringify({payments}),{
status: 200,
});
}
};

View File

@ -1,26 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { Payment } from '../../../../models/Payment';
import { dbConnect, dbDisconnect } from '../../../../utils/db';
import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
import { User } from '../../../../models/User';
// header: use for bearer token for now
// recipe json in body
export const GET: RequestHandler = async ({request, cookies}) => {
const user = await authenticateUser(cookies)
if(!user){
throw error(403, "Not logged in")
}
else if(!user.access.includes("abrechnung")){
throw error(403, "This user does not have edit permissions for payments")
}
else{
await dbConnect();
const users = await User.find({access: "abrechnung"}, 'username').lean()
await dbDisconnect();
return new Response(JSON.stringify({users}),{
status: 200,
});
}
};

View File

@ -2,29 +2,28 @@ import type { RequestHandler } from '@sveltejs/kit';
import { Recipe } from '../../../../models/Recipe'; import { Recipe } from '../../../../models/Recipe';
import { dbConnect, dbDisconnect } from '../../../../utils/db'; import { dbConnect, dbDisconnect } from '../../../../utils/db';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';;
// 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, cookies}) => { export const POST: RequestHandler = async ({request, cookies, locals}) => {
let message = await request.json() let message = await request.json()
const recipe_json = message.recipe const recipe_json = message.recipe
const user = await authenticateUser(cookies) let auth = await locals.auth();
if(!user){ /*const user = session.user;*/
console.log(auth)
if(!auth){
throw error(401, "Not logged in") throw error(401, "Not logged in")
} }
if(!user.access.includes("rezepte")){ /*if(!user.access.includes("rezepte")){
throw error(401, "This user does not have permissions to add recipes") throw error(401, "This user does not have permissions to add recipes")
} }*/
else{ await dbConnect();
await dbConnect(); try{
try{ await Recipe.create(recipe_json);
await Recipe.create(recipe_json); } catch(e){
} catch(e){ throw error(400, e)
throw error(400, e) }
} await dbDisconnect();
await dbDisconnect(); return new Response(JSON.stringify({msg: "Added recipe successfully"}),{
return new Response(JSON.stringify({msg: "Added recipe successfully"}),{ status: 200,
status: 200, });
});
}
}; };

View File

@ -3,15 +3,13 @@ import { Recipe } from '../../../../models/Recipe';
import { dbConnect, dbDisconnect } from '../../../../utils/db'; import { dbConnect, dbDisconnect } from '../../../../utils/db';
import type {RecipeModelType} from '../../../../types/types'; import type {RecipeModelType} from '../../../../types/types';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
// 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, cookies}) => { export const POST: RequestHandler = async ({request, locals}) => {
let message = await request.json() let message = await request.json()
const user = await authenticateUser(cookies) const auth = await locals.auth();
if(!user) throw error(401, "Need to be logged in") if(!auth) throw error(401, "Need to be logged in")
if(!user.access.includes("rezepte")) throw error(401, "Insufficient permissions")
const short_name = message.old_short_name const short_name = message.old_short_name
await dbConnect(); await dbConnect();

View File

@ -3,20 +3,15 @@ import { Recipe } from '../../../../models/Recipe';
import { dbConnect, dbDisconnect } from '../../../../utils/db'; import { dbConnect, dbDisconnect } from '../../../../utils/db';
import type {RecipeModelType} from '../../../../types/types'; import type {RecipeModelType} from '../../../../types/types';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
// 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, cookies}) => { export const POST: RequestHandler = async ({request, locals}) => {
let message = await request.json() let message = await request.json()
const recipe_json = message.recipe const recipe_json = message.recipe
const user = await authenticateUser(cookies) const auth = await locals.auth();
console.log(user) if(!auth){
if(!user){
throw error(403, "Not logged in") throw error(403, "Not logged in")
} }
else if(!user.access.includes("rezepte")){
throw error(403, "This user does not have edit permissions for recipes")
}
else{ else{
await dbConnect(); await dbConnect();
await Recipe.findOneAndUpdate({short_name: message.old_short_name }, recipe_json); await Recipe.findOneAndUpdate({short_name: message.old_short_name }, recipe_json);

View File

@ -3,13 +3,11 @@ import type { RequestHandler } from '@sveltejs/kit';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import { IMAGE_DIR } from '$env/static/private' import { IMAGE_DIR } from '$env/static/private'
import sharp from 'sharp'; import sharp from 'sharp';
import { authenticateUser } from '$lib/js/authenticate';
export const POST = (async ({ request, cookies }) => { export const POST = (async ({ request, locals}) => {
const data = await request.json(); const data = await request.json();
const user = await authenticateUser(cookies) const auth = await locals.auth();
if (!user) throw error(401, "Need to be logged in") if (!auth) throw error(401, "Need to be logged in")
if (!user.access.includes("rezepte")) throw error(401, "You don't have sufficient permissions for this")
let full_res = new Buffer.from(data.image, 'base64') let full_res = new Buffer.from(data.image, 'base64')
// reduce image size if over 500KB // reduce image size if over 500KB
const MAX_SIZE_KB = 500 const MAX_SIZE_KB = 500

View File

@ -3,13 +3,12 @@ import type { RequestHandler } from '@sveltejs/kit';
import { IMAGE_DIR } from '$env/static/private' import { IMAGE_DIR } from '$env/static/private'
import { unlink } from 'node:fs'; import { unlink } from 'node:fs';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';;
export const POST = (async ({ request, cookies }) => { export const POST = (async ({ request, locals}) => {
const data = await request.json(); const data = await request.json();
const user = await authenticateUser(cookies) const auth = await locals.auth()
if(!user) throw error(401, "You need to be logged in") if(!auth) throw error(401, "You need to be logged in")
if(!user.access.includes("rezepte")) throw error(401, "Your don't have the required permission for this")
[ "full", "thumb", "placeholder"].forEach((folder) => { [ "full", "thumb", "placeholder"].forEach((folder) => {
unlink(path.join(IMAGE_DIR, "rezepte", folder, data.name + ".webp"), (e) => { unlink(path.join(IMAGE_DIR, "rezepte", folder, data.name + ".webp"), (e) => {
if(e) error(404, "could not delete: " + folder + "/" + data.name + ".webp" + e) if(e) error(404, "could not delete: " + folder + "/" + data.name + ".webp" + e)

View File

@ -3,13 +3,11 @@ import type { RequestHandler } from '@sveltejs/kit';
import { IMAGE_DIR } from '$env/static/private' import { IMAGE_DIR } from '$env/static/private'
import { rename } from 'node:fs'; import { rename } from 'node:fs';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import { authenticateUser } from '$lib/js/authenticate';
export const POST = (async ({ request, cookies }) => { export const POST = (async ({ request, locals}) => {
const data = await request.json(); const data = await request.json();
const user = await authenticateUser(cookies) const auth = await locals.auth();
if(!user) throw error(401, "need to be logged in") if(!auth ) throw error(401, "need to be logged in")
if(!user.access.includes("rezepte")) throw error(401, "You don't have the required permission to do this")
[ "full", "thumb", "placeholder"].forEach((folder) => { [ "full", "thumb", "placeholder"].forEach((folder) => {
const old_path = path.join(IMAGE_DIR, "rezepte", folder, data.old_name + ".webp") const old_path = path.join(IMAGE_DIR, "rezepte", folder, data.old_name + ".webp")

View File

@ -1,5 +1,8 @@
import { get_username } from '$lib/js/get_username';; import type { Actions, PageServerLoad } from "./$types"
import { error } from "@sveltejs/kit"
export const load = (async ({cookies}) => { export const load = (async ({cookies, locals}) => {
return { user: await get_username(cookies) } return {
session: await locals.getSession()
}
}); });

View File

@ -3,8 +3,8 @@ import Header from '$lib/components/Header.svelte'
import UserHeader from '$lib/components/UserHeader.svelte'; import UserHeader from '$lib/components/UserHeader.svelte';
export let data export let data
let username = "" let username = ""
if(data.user){ if(data.session){
username = data.user.username username = data.session.user.name
} }
</script> </script>