diff --git a/src/routes/(main)/abrechnung/+page.svelte b/src/routes/(main)/abrechnung/+page.svelte
index 8ecd334..018cef2 100644
--- a/src/routes/(main)/abrechnung/+page.svelte
+++ b/src/routes/(main)/abrechnung/+page.svelte
@@ -1,10 +1 @@
-
-
-
+
WIP
diff --git a/src/routes/(main)/login/+page.server.ts b/src/routes/(main)/login/+page.server.ts
index 4d07f8a..f8ebd72 100644
--- a/src/routes/(main)/login/+page.server.ts
+++ b/src/routes/(main)/login/+page.server.ts
@@ -11,7 +11,7 @@ export const load: PageServerLoad = async ({ locals }) => {
export const actions: Actions = {
login: async (event) => {
const data = await event.request.formData()
- const res = await event.fetch('/api/login',
+ const res = await event.fetch('/api/user/login',
{method: 'POST',
body: JSON.stringify({
username: data.get('username'),
diff --git a/src/routes/(main)/register/+page.server.ts b/src/routes/(main)/register/+page.server.ts
index 5f92c0c..5f5b626 100644
--- a/src/routes/(main)/register/+page.server.ts
+++ b/src/routes/(main)/register/+page.server.ts
@@ -10,7 +10,7 @@ export const load: PageServerLoad = async ({ locals }) => {
export const actions: Actions = {
register: async (event) => {
const data = await event.request.formData();
- const res = await event.fetch('/api/register',
+ const res = await event.fetch('/api/user/register',
{method: 'POST',
body: JSON.stringify({
diff --git a/src/routes/(main)/settings/+page.server.ts b/src/routes/(main)/settings/+page.server.ts
index 0f60df9..1f2ba02 100644
--- a/src/routes/(main)/settings/+page.server.ts
+++ b/src/routes/(main)/settings/+page.server.ts
@@ -15,7 +15,7 @@ export const actions: Actions = {
},
login: async (event) => {
const data = await event.request.formData()
- const res = await event.fetch('/api/login',
+ const res = await event.fetch('/api/user/login',
{method: 'POST',
body: JSON.stringify({
username: data.get('username'),
diff --git a/src/routes/(rezepte)/rezepte/+page.server.ts b/src/routes/(rezepte)/rezepte/+page.server.ts
index f6e2ade..6bc2e24 100644
--- a/src/routes/(rezepte)/rezepte/+page.server.ts
+++ b/src/routes/(rezepte)/rezepte/+page.server.ts
@@ -2,8 +2,8 @@ import type { PageServerLoad } from "./$types";
export async function load({ fetch }) {
let current_month = new Date().getMonth() + 1
- const res_season = await fetch(`/api/items/in_season/` + current_month);
- const res_all_brief = await fetch(`/api/items/all_brief`);
+ const res_season = await fetch(`/api/rezepte/items/in_season/` + current_month);
+ const res_all_brief = await fetch(`/api/rezepte/items/all_brief`);
const item_season = await res_season.json();
const item_all_brief = await res_all_brief.json();
return {
diff --git a/src/routes/(rezepte)/rezepte/[name]/+page.ts b/src/routes/(rezepte)/rezepte/[name]/+page.ts
index faecdd4..b6487ee 100644
--- a/src/routes/(rezepte)/rezepte/[name]/+page.ts
+++ b/src/routes/(rezepte)/rezepte/[name]/+page.ts
@@ -1,7 +1,7 @@
import { error } from "@sveltejs/kit";
export async function load({ fetch, params}) {
- const res = await fetch(`/api/items/${params.name}`);
+ const res = await fetch(`/api/rezepte/items/${params.name}`);
let item = await res.json();
if(!res.ok){
throw error(res.status, item.message)
diff --git a/src/routes/(rezepte)/rezepte/add/+page.svelte b/src/routes/(rezepte)/rezepte/add/+page.svelte
index a047c78..d624e4c 100644
--- a/src/routes/(rezepte)/rezepte/add/+page.svelte
+++ b/src/routes/(rezepte)/rezepte/add/+page.svelte
@@ -86,7 +86,7 @@
image: img_local,
name: short_name,
}
- await fetch(`/api/img/add`, {
+ await fetch(`/api/rezepte/img/add`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -101,7 +101,7 @@
upload_img()
console.log(add_info.total_time)
- const res = await fetch('/api/add', {
+ const res = await fetch('/api/rezepte/add', {
method: 'POST',
body: JSON.stringify({
recipe: {
diff --git a/src/routes/(rezepte)/rezepte/category/+page.ts b/src/routes/(rezepte)/rezepte/category/+page.ts
index 0381050..666d883 100644
--- a/src/routes/(rezepte)/rezepte/category/+page.ts
+++ b/src/routes/(rezepte)/rezepte/category/+page.ts
@@ -1,7 +1,7 @@
import type { PageLoad } from "./$types";
export async function load({ fetch}) {
- const res = await fetch(`/api/items/category`);
+ const res = await fetch(`/api/rezepte/items/category`);
const categories= await res.json();
return {categories}
};
diff --git a/src/routes/(rezepte)/rezepte/category/[category]/+page.ts b/src/routes/(rezepte)/rezepte/category/[category]/+page.ts
index a21ae88..c49346d 100644
--- a/src/routes/(rezepte)/rezepte/category/[category]/+page.ts
+++ b/src/routes/(rezepte)/rezepte/category/[category]/+page.ts
@@ -1,7 +1,7 @@
import type { PageLoad } from "./$types";
export async function load({ fetch, params }) {
- const res = await fetch(`/api/items/category/${params.category}`);
+ const res = await fetch(`/api/rezepte/items/category/${params.category}`);
const items = await res.json();
return {
category: params.category,
diff --git a/src/routes/(rezepte)/rezepte/edit/[name]/+page.server.ts b/src/routes/(rezepte)/rezepte/edit/[name]/+page.server.ts
index a28d9ca..081f885 100644
--- a/src/routes/(rezepte)/rezepte/edit/[name]/+page.server.ts
+++ b/src/routes/(rezepte)/rezepte/edit/[name]/+page.server.ts
@@ -2,7 +2,7 @@ import type { PageLoad } from "./$types";
export async function load({ fetch, params, locals}) {
let current_month = new Date().getMonth() + 1
- const res = await fetch(`/api/items/${params.name}`);
+ const res = await fetch(`/api/rezepte/items/${params.name}`);
const recipe = await res.json();
return {recipe: recipe,
user: locals.user
diff --git a/src/routes/(rezepte)/rezepte/edit/[name]/+page.svelte b/src/routes/(rezepte)/rezepte/edit/[name]/+page.svelte
index 647e08c..96de157 100644
--- a/src/routes/(rezepte)/rezepte/edit/[name]/+page.svelte
+++ b/src/routes/(rezepte)/rezepte/edit/[name]/+page.svelte
@@ -96,7 +96,7 @@
if(!response){
return
}
- const res_img = await fetch('/api/img/delete', {
+ const res_img = await fetch('/api/rezepte/img/delete', {
method: 'POST',
body: JSON.stringify({
name: old_short_name,
@@ -112,7 +112,7 @@
return
}
return
- const res = await fetch('/api/delete', {
+ const res = await fetch('/api/rezepte/delete', {
method: 'POST',
body: JSON.stringify({
old_short_name,
@@ -141,7 +141,7 @@
console.log("img_local", img_local)
if(img_local != ""){
async function delete_img(){
- const res = await fetch('/api/img/delete', {
+ const res = await fetch('/api/rezepte/img/delete', {
method: 'POST',
body: JSON.stringify({
name: old_short_name,
@@ -161,7 +161,7 @@
image: img_local,
name: short_name,
}
- const res = await fetch(`/api/img/add`, {
+ const res = await fetch(`/api/rezepte/img/add`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -181,7 +181,7 @@
// case new short_name:
else if(short_name != old_short_name){
console.log("MOVING")
- const res_img = await fetch('/api/img/mv', {
+ const res_img = await fetch('/api/rezepte/img/mv', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -199,7 +199,7 @@
return
}
}
- const res = await fetch('/api/edit', {
+ const res = await fetch('/api/rezepte/edit', {
method: 'POST',
body: JSON.stringify({
recipe: {
diff --git a/src/routes/(rezepte)/rezepte/icon/+page.ts b/src/routes/(rezepte)/rezepte/icon/+page.ts
index f788408..c3df7f8 100644
--- a/src/routes/(rezepte)/rezepte/icon/+page.ts
+++ b/src/routes/(rezepte)/rezepte/icon/+page.ts
@@ -2,7 +2,7 @@ import type { PageLoad } from "./$types";
export async function load({ fetch }) {
let current_month = new Date().getMonth() + 1
- const res_icons = await fetch(`/api/items/icon`);
+ const res_icons = await fetch(`/api/rezepte/items/icon`);
const item = await res_icons.json();
return {
icons: item,
diff --git a/src/routes/(rezepte)/rezepte/icon/[icon]/+page.ts b/src/routes/(rezepte)/rezepte/icon/[icon]/+page.ts
index 064261f..c33ab08 100644
--- a/src/routes/(rezepte)/rezepte/icon/[icon]/+page.ts
+++ b/src/routes/(rezepte)/rezepte/icon/[icon]/+page.ts
@@ -1,8 +1,8 @@
import type { PageLoad } from "./$types";
export async function load({ fetch, params }) {
- const res_season = await fetch(`/api/items/icon/` + params.icon);
- const res_icons = await fetch(`/api/items/icon`);
+ const res_season = await fetch(`/api/rezepte/items/icon/` + params.icon);
+ const res_icons = await fetch(`/api/rezepte/items/icon`);
const icons = await res_icons.json();
const item_season = await res_season.json();
return {
diff --git a/src/routes/(rezepte)/rezepte/season/+page.ts b/src/routes/(rezepte)/rezepte/season/+page.ts
index 0ff98a1..80a6d3f 100644
--- a/src/routes/(rezepte)/rezepte/season/+page.ts
+++ b/src/routes/(rezepte)/rezepte/season/+page.ts
@@ -2,7 +2,7 @@ import type { PageLoad } from "./$types";
export async function load({ fetch }) {
let current_month = new Date().getMonth() + 1
- const res_season = await fetch(`/api/items/in_season/` + current_month);
+ const res_season = await fetch(`/api/rezepte/items/in_season/` + current_month);
const item_season = await res_season.json();
return {
season: item_season,
diff --git a/src/routes/(rezepte)/rezepte/season/[month]/+page.ts b/src/routes/(rezepte)/rezepte/season/[month]/+page.ts
index 6e66f10..ea4c55a 100644
--- a/src/routes/(rezepte)/rezepte/season/[month]/+page.ts
+++ b/src/routes/(rezepte)/rezepte/season/[month]/+page.ts
@@ -1,8 +1,8 @@
import type { PageLoad } from "./$types";
export async function load({ fetch, params }) {
- const res_season = await fetch(`/api/items/in_season/` + params.month);
- const res_all_brief = await fetch(`/api/items/all_brief`);
+ const res_season = await fetch(`/api/rezepte/items/in_season/` + params.month);
+ const res_all_brief = await fetch(`/api/rezepte/items/all_brief`);
const item_season = await res_season.json();
const item_all_brief = await res_all_brief.json();
return {
diff --git a/src/routes/(rezepte)/rezepte/tag/+page.ts b/src/routes/(rezepte)/rezepte/tag/+page.ts
index 9f687a2..34a3755 100644
--- a/src/routes/(rezepte)/rezepte/tag/+page.ts
+++ b/src/routes/(rezepte)/rezepte/tag/+page.ts
@@ -1,7 +1,7 @@
import type { PageLoad } from "./$types";
export async function load({ fetch}) {
- const res = await fetch(`/api/items/tag`);
+ const res = await fetch(`/api/rezepte/items/tag`);
const tags = await res.json();
return {tags}
};
diff --git a/src/routes/(rezepte)/rezepte/tag/[tag]/+page.ts b/src/routes/(rezepte)/rezepte/tag/[tag]/+page.ts
index ac99b03..0d4e238 100644
--- a/src/routes/(rezepte)/rezepte/tag/[tag]/+page.ts
+++ b/src/routes/(rezepte)/rezepte/tag/[tag]/+page.ts
@@ -1,7 +1,7 @@
import type { PageLoad } from "./$types";
export async function load({ fetch, params }) {
- const res_tag = await fetch(`/api/items/tag/${params.tag}`);
+ const res_tag = await fetch(`/api/rezepte/items/tag/${params.tag}`);
const items_tag = await res_tag.json();
return {
tag: params.tag,
diff --git a/src/routes/api/rezepte/add/+server.ts b/src/routes/api/rezepte/add/+server.ts
new file mode 100644
index 0000000..9df6ca8
--- /dev/null
+++ b/src/routes/api/rezepte/add/+server.ts
@@ -0,0 +1,30 @@
+import type { RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../models/Recipe';
+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 recipe_json = message.recipe
+ const user = await authenticateUser(cookies)
+ if(!user){
+ throw error(401, "Not logged in")
+ }
+ if(!user.access.includes("rezepte")){
+ throw error(401, "This user does not have permissions to add recipes")
+ }
+ else{
+ await dbConnect();
+ try{
+ await Recipe.create(recipe_json);
+ } catch(e){
+ throw error(400, e)
+ }
+ await dbDisconnect();
+ return new Response(JSON.stringify({msg: "Added recipe successfully"}),{
+ status: 200,
+ });
+ }
+};
diff --git a/src/routes/api/rezepte/delete/+server.ts b/src/routes/api/rezepte/delete/+server.ts
new file mode 100644
index 0000000..98479d7
--- /dev/null
+++ b/src/routes/api/rezepte/delete/+server.ts
@@ -0,0 +1,23 @@
+import type { RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../utils/db';
+import type {RecipeModelType} from '../../../../types/types';
+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 user = await authenticateUser(cookies)
+ if(!user) 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
+ await dbConnect();
+ await Recipe.findOneAndDelete({short_name: short_name});
+ await dbDisconnect();
+ return new Response(JSON.stringify({msg: "Deleted recipe successfully"}),{
+ status: 200,
+ });
+}
diff --git a/src/routes/api/rezepte/edit/+server.ts b/src/routes/api/rezepte/edit/+server.ts
new file mode 100644
index 0000000..b608732
--- /dev/null
+++ b/src/routes/api/rezepte/edit/+server.ts
@@ -0,0 +1,29 @@
+import type { RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../utils/db';
+import type {RecipeModelType} from '../../../../types/types';
+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 recipe_json = message.recipe
+ const user = await authenticateUser(cookies)
+ console.log(user)
+ if(!user){
+ 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{
+ await dbConnect();
+ await Recipe.findOneAndUpdate({short_name: message.old_short_name }, recipe_json);
+ await dbDisconnect();
+ return new Response(JSON.stringify({msg: "Edited recipe successfully"}),{
+ status: 200,
+ });
+
+ }
+};
diff --git a/src/routes/api/rezepte/img/add/+server.ts b/src/routes/api/rezepte/img/add/+server.ts
new file mode 100644
index 0000000..fa51487
--- /dev/null
+++ b/src/routes/api/rezepte/img/add/+server.ts
@@ -0,0 +1,46 @@
+import path from 'path'
+import type { RequestHandler } from '@sveltejs/kit';
+import { error } from '@sveltejs/kit';
+import { IMAGE_DIR } from '$env/static/private'
+import sharp from 'sharp';
+import { authenticateUser } from '$lib/js/authenticate';
+
+export const POST = (async ({ request, cookies }) => {
+ const data = await request.json();
+ const user = await authenticateUser(cookies)
+ if (!user) 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')
+ // reduce image size if over 500KB
+ const MAX_SIZE_KB = 500
+ //const metadata = await sharp(full_res).metadata()
+ ////reduce image size if larger than 500KB
+ //if(metadata.size > MAX_SIZE_KB*1000){
+ // full_res = sharp(full_res).
+ // webp( { quality: 70})
+ // .toBuffer()
+ //}
+ await sharp(full_res)
+ .toFormat('webp')
+ .toFile(path.join(IMAGE_DIR,
+ "rezepte",
+ "full",
+ data.name + ".webp"))
+ await sharp(full_res)
+ .resize({ width: 800})
+ .toFormat('webp')
+ .toFile(path.join(IMAGE_DIR,
+ "rezepte",
+ "thumb",
+ data.name + ".webp"))
+ await sharp(full_res)
+ .resize({ width: 20})
+ .toFormat('webp')
+ .toFile(path.join(IMAGE_DIR,
+ "rezepte",
+ "placeholder",
+ data.name + ".webp"))
+ return new Response(JSON.stringify({msg: "Added image successfully"}),{
+ status: 200,
+ });
+}) satisfies RequestHandler;
diff --git a/src/routes/api/rezepte/img/delete/+server.ts b/src/routes/api/rezepte/img/delete/+server.ts
new file mode 100644
index 0000000..6fd1691
--- /dev/null
+++ b/src/routes/api/rezepte/img/delete/+server.ts
@@ -0,0 +1,21 @@
+import path from 'path'
+import type { RequestHandler } from '@sveltejs/kit';
+import { IMAGE_DIR } from '$env/static/private'
+import { unlink } from 'node:fs';
+import { error } from '@sveltejs/kit';
+import { authenticateUser } from '$lib/js/authenticate';;
+
+export const POST = (async ({ request, cookies }) => {
+ const data = await request.json();
+ const user = await authenticateUser(cookies)
+ if(!user) 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) => {
+ unlink(path.join(IMAGE_DIR, "rezepte", folder, data.name + ".webp"), (e) => {
+ if(e) error(404, "could not delete: " + folder + "/" + data.name + ".webp" + e)
+ })
+ })
+ return new Response(JSON.stringify({msg: "Deleted image successfully"}),{
+ status: 200,
+ });
+}) satisfies RequestHandler;
diff --git a/src/routes/api/rezepte/img/mv/+server.ts b/src/routes/api/rezepte/img/mv/+server.ts
new file mode 100644
index 0000000..7add42e
--- /dev/null
+++ b/src/routes/api/rezepte/img/mv/+server.ts
@@ -0,0 +1,25 @@
+import path from 'path'
+import type { RequestHandler } from '@sveltejs/kit';
+import { IMAGE_DIR } from '$env/static/private'
+import { rename } from 'node:fs';
+import { error } from '@sveltejs/kit';
+import { authenticateUser } from '$lib/js/authenticate';
+
+export const POST = (async ({ request, cookies }) => {
+ const data = await request.json();
+ const user = await authenticateUser(cookies)
+ if(!user) 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) => {
+ const old_path = path.join(IMAGE_DIR, "rezepte", folder, data.old_name + ".webp")
+ rename(old_path, path.join(IMAGE_DIR, "rezepte", folder, data.new_name + ".webp"), (e) => {
+ console.log(e)
+ if(e) throw error(500, "could not mv: " + old_path)
+ })
+ });
+
+ return new Response(JSON.stringify({msg: "Deleted image successfully"}),{
+ status: 200,
+ });
+}) satisfies RequestHandler;
diff --git a/src/routes/api/rezepte/items/[name]/+server.ts b/src/routes/api/rezepte/items/[name]/+server.ts
new file mode 100644
index 0000000..cd3652c
--- /dev/null
+++ b/src/routes/api/rezepte/items/[name]/+server.ts
@@ -0,0 +1,17 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../../utils/db';
+import type {RecipeModelType} from '../../../../../types/types';
+import { error } from '@sveltejs/kit';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let recipe = (await Recipe.findOne({ short_name: params.name}).lean()) as RecipeModelType[];
+ await dbDisconnect();
+
+ recipe = JSON.parse(JSON.stringify(recipe));
+ if(recipe == null){
+ throw error(404, "Recipe not found")
+ }
+ return json(recipe);
+};
diff --git a/src/routes/api/rezepte/items/all_brief/+server.ts b/src/routes/api/rezepte/items/all_brief/+server.ts
new file mode 100644
index 0000000..a95d44d
--- /dev/null
+++ b/src/routes/api/rezepte/items/all_brief/+server.ts
@@ -0,0 +1,12 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import type { BriefRecipeType } from '../../../../../types/types';
+import { Recipe } from '../../../../../models/Recipe'
+import { dbConnect, dbDisconnect } from '../../../../../utils/db';
+import { rand_array } from '$lib/js/randomize';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let found_brief = rand_array(await Recipe.find({}, 'name short_name tags category icon description season').lean()) as BriefRecipeType[];
+ await dbDisconnect();
+ return json(JSON.parse(JSON.stringify(found_brief)));
+};
diff --git a/src/routes/api/rezepte/items/category/+server.ts b/src/routes/api/rezepte/items/category/+server.ts
new file mode 100644
index 0000000..6fe5113
--- /dev/null
+++ b/src/routes/api/rezepte/items/category/+server.ts
@@ -0,0 +1,13 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../../utils/db';
+import type {BriefRecipeType} from '../../../../../types/types';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let categories = (await Recipe.distinct('category').lean());
+ await dbDisconnect();
+
+ categories= JSON.parse(JSON.stringify(categories));
+ return json(categories);
+};
diff --git a/src/routes/api/rezepte/items/category/[category]/+server.ts b/src/routes/api/rezepte/items/category/[category]/+server.ts
new file mode 100644
index 0000000..2891d0a
--- /dev/null
+++ b/src/routes/api/rezepte/items/category/[category]/+server.ts
@@ -0,0 +1,14 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../../../utils/db';
+import type {BriefRecipeType} from '../../../../../../types/types';
+import { rand_array } from '$lib/js/randomize';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let recipes = rand_array(await Recipe.find({category: params.category}, 'name short_name images tags category icon description season').lean()) as BriefRecipeType[];
+ await dbDisconnect();
+
+ recipes = JSON.parse(JSON.stringify(recipes));
+ return json(recipes);
+};
diff --git a/src/routes/api/rezepte/items/icon/+server.ts b/src/routes/api/rezepte/items/icon/+server.ts
new file mode 100644
index 0000000..f82ac7f
--- /dev/null
+++ b/src/routes/api/rezepte/items/icon/+server.ts
@@ -0,0 +1,13 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../../utils/db';
+import type {BriefRecipeType} from '../../../../../types/types';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let icons = (await Recipe.distinct('icon').lean());
+ await dbDisconnect();
+
+ icons = JSON.parse(JSON.stringify(icons));
+ return json(icons);
+};
diff --git a/src/routes/api/rezepte/items/icon/[icon]/+server.ts b/src/routes/api/rezepte/items/icon/[icon]/+server.ts
new file mode 100644
index 0000000..631ec9b
--- /dev/null
+++ b/src/routes/api/rezepte/items/icon/[icon]/+server.ts
@@ -0,0 +1,14 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../../../utils/db';
+import type {BriefRecipeType} from '../../../../../../types/types';
+import { rand_array } from '$lib/js/randomize';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let recipes = rand_array(await Recipe.find({icon: params.icon}, 'name short_name images tags category icon description season').lean()) as BriefRecipeType[];
+ await dbDisconnect();
+
+ recipes = JSON.parse(JSON.stringify(recipes));
+ return json(recipes);
+};
diff --git a/src/routes/api/rezepte/items/in_season/[month]/+server.ts b/src/routes/api/rezepte/items/in_season/[month]/+server.ts
new file mode 100644
index 0000000..8660f4b
--- /dev/null
+++ b/src/routes/api/rezepte/items/in_season/[month]/+server.ts
@@ -0,0 +1,13 @@
+import type {rand_array} from '$lib/js/randomize';
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../../models/Recipe'
+import { dbConnect, dbDisconnect } from '../../../../../../utils/db';
+import { rand_array } from '$lib/js/randomize';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let found_in_season = rand_array(await Recipe.find({season: params.month}, 'name short_name images tags category icon description season').lean());
+ await dbDisconnect();
+ found_in_season = JSON.parse(JSON.stringify(found_in_season));
+ return json(found_in_season);
+};
diff --git a/src/routes/api/rezepte/items/tag/+server.ts b/src/routes/api/rezepte/items/tag/+server.ts
new file mode 100644
index 0000000..258ce6f
--- /dev/null
+++ b/src/routes/api/rezepte/items/tag/+server.ts
@@ -0,0 +1,13 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../../utils/db';
+import type {BriefRecipeType} from '../../../../../types/types';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let categories = (await Recipe.distinct('tags').lean());
+ await dbDisconnect();
+
+ categories= JSON.parse(JSON.stringify(categories));
+ return json(categories);
+};
diff --git a/src/routes/api/rezepte/items/tag/[tag]/+server.ts b/src/routes/api/rezepte/items/tag/[tag]/+server.ts
new file mode 100644
index 0000000..cfa00d3
--- /dev/null
+++ b/src/routes/api/rezepte/items/tag/[tag]/+server.ts
@@ -0,0 +1,14 @@
+import { json, type RequestHandler } from '@sveltejs/kit';
+import { Recipe } from '../../../../../../models/Recipe';
+import { dbConnect, dbDisconnect } from '../../../../../../utils/db';
+import type {BriefRecipeType} from '../../../../../../types/types';
+import { rand_array } from '$lib/js/randomize';
+
+export const GET: RequestHandler = async ({params}) => {
+ await dbConnect();
+ let recipes = rand_array(await Recipe.find({tags: params.tag}, 'name short_name images tags category icon description season').lean()) as BriefRecipeType[];
+ await dbDisconnect();
+
+ recipes = JSON.parse(JSON.stringify(recipes));
+ return json(recipes);
+};
diff --git a/src/routes/api/user/admin/users/+server.ts b/src/routes/api/user/admin/users/+server.ts
new file mode 100644
index 0000000..0926f05
--- /dev/null
+++ b/src/routes/api/user/admin/users/+server.ts
@@ -0,0 +1,23 @@
+import type { RequestHandler } from '@sveltejs/kit';
+import { error } from '@sveltejs/kit';
+
+import { dbConnect, dbDisconnect } from '../../../../../utils/db';
+import { User } from '../../../../../models/User';
+import { get_username } from '$lib/js/get_username';
+
+// header: use for bearer token for now
+// recipe json in body
+export const POST: RequestHandler = async ({cookies}) => {
+ const requesting_user = await get_username(cookies)
+ await dbConnect()
+ let res = await User.findOne({username: requesting_user}, 'access').lean()
+ if(!res.access.contains("admin")){
+ await dbDisconnect()
+ throw error(401, {message: "Your user does not have the permissions to do this"})
+ }
+ else{
+ let res = await User.find({}, 'username access').lean()
+ await dbDisconnect()
+ return { res }
+ }
+};
diff --git a/src/routes/api/user/change_pw/+server.ts b/src/routes/api/user/change_pw/+server.ts
new file mode 100644
index 0000000..7a82df7
--- /dev/null
+++ b/src/routes/api/user/change_pw/+server.ts
@@ -0,0 +1,40 @@
+import type { RequestHandler } from '@sveltejs/kit';
+import { error } from '@sveltejs/kit';
+import { hash } from 'argon2';
+
+import { PEPPER } from '$env/static/private';
+
+import { User } from '../../../../models/User';
+import { dbConnect, dbDisconnect } from '../../../../utils/db';
+
+// header: use for bearer token for now
+// recipe json in body
+export const POST: RequestHandler = async ({request}) => {
+ const {username, old_password, new_password} = await request.json()
+ await dbConnect();
+ const salt = await User.findOne({username: username}, 'salt');
+ const pass_hash = await hashPassword(old_password + PEPPER, salt)
+ try{
+ await User.updateOne({
+ username: username,
+ pass_hash: pass_hash,
+ })
+ }catch(e){
+ await dbDisconnect();
+ throw error(400, e);
+ }
+ await dbDisconnect();
+ return new Response(JSON.stringify({message: "User added successfully"}),
+ {status: 200}
+ );
+ }
+};
+
+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);
+ }
+}
diff --git a/src/routes/api/user/login/+server.ts b/src/routes/api/user/login/+server.ts
new file mode 100644
index 0000000..e5e24d5
--- /dev/null
+++ b/src/routes/api/user/login/+server.ts
@@ -0,0 +1,46 @@
+import type { RequestHandler } from '@sveltejs/kit';
+import { error } from '@sveltejs/kit';
+import pkg from 'jsonwebtoken';
+const { sign } = pkg;
+import { verify} from 'argon2';
+import { COOKIE_SECRET } from '$env/static/private'
+import { PEPPER } from '$env/static/private'
+
+import { dbConnect, dbDisconnect } from '../../../../utils/db';
+import { User } from '../../../../models/User';
+
+// header: use for bearer token for now
+// recipe json in body
+export const POST: RequestHandler = async ({request}) => {
+ const {username, password} = await request.json()
+ await dbConnect()
+ let res = await User.findOne({username: username}, 'pass_hash salt').lean()
+ await dbDisconnect()
+ if(!res){
+ console.log("NOT FOUND")
+ throw error(401, {message: "wrong password or user does not exist"})
+ }
+
+ const stored_pw = res.pass_hash
+ const salt = res.salt
+
+ const isMatch = await verify(stored_pw, password + PEPPER, {salt})
+ if(!isMatch){
+ throw error(401, {message: "wrong password or user does not exist"})
+ }
+
+ res = await createJWT(username)
+ return new Response(JSON.stringify(res))
+};
+
+async function createJWT(username) {
+ const payload = {
+ username: username,
+ };
+
+ const masterSecret = COOKIE_SECRET;
+ const secretKey = masterSecret;
+ const jwt = sign(payload, secretKey);
+ console.log(jwt)
+ return jwt
+}
diff --git a/src/routes/api/user/register/+server.ts b/src/routes/api/user/register/+server.ts
new file mode 100644
index 0000000..8b91f63
--- /dev/null
+++ b/src/routes/api/user/register/+server.ts
@@ -0,0 +1,50 @@
+import type { RequestHandler } from '@sveltejs/kit';
+import { error } from '@sveltejs/kit';
+import { hash } from 'argon2';
+import { randomBytes } from 'crypto';
+import { ALLOW_REGISTRATION } from '$env/static/private';
+import { PEPPER } from '$env/static/private';
+
+import { User } from '../../../../models/User';
+import { dbConnect, dbDisconnect } from '../../../../utils/db';
+
+// header: use for bearer token for now
+// recipe json in body
+export const POST: RequestHandler = async ({request}) => {
+ if(ALLOW_REGISTRATION){
+ const {username, password} = await request.json()
+ const salt = randomBytes(32).toString('hex'); // Generate a random salt
+
+ const pass_hash = await hashPassword(password + PEPPER, salt)
+ await dbConnect();
+ try{
+ await User.create({
+ username: username,
+ pass_hash: pass_hash,
+ salt: salt,
+ access: [],
+ })
+ }catch(e){
+ await dbDisconnect();
+ throw error(400, e);
+ }
+ await dbDisconnect();
+ return new Response(JSON.stringify({message: "User added successfully"}),
+ {status: 200}
+ );
+ }
+ else{
+ throw error(401, "user registration currently closed")
+ }
+
+
+};
+
+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);
+ }
+}