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); + } +}