From 2db750885974d388a7520ab279ede78e2a8e86ca Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Wed, 19 Mar 2025 20:43:47 -0300 Subject: [PATCH] Filtern nach ID --- .../Dashboard/DashboardSidebar.svelte | 7 +- src/modules/Dashboard/DashboardModule.svelte | 10 ++- src/modules/ImpersonateUserModule.svelte | 34 ++++++++ src/pages/api/user/index.ts | 38 ++++++++- .../dashboard/admin/impersonate-user.astro | 33 ++++++++ src/pages/dashboard/admin/impersonate.astro | 66 ++++++++++++++++ src/pages/dashboard/objekte/[page].astro | 79 ++++++++++++++++++- src/pages/pdf/ansichtsausweis.ts | 4 +- src/pages/pdf/datenblatt.ts | 4 +- 9 files changed, 262 insertions(+), 13 deletions(-) create mode 100644 src/modules/ImpersonateUserModule.svelte create mode 100644 src/pages/dashboard/admin/impersonate-user.astro create mode 100644 src/pages/dashboard/admin/impersonate.astro diff --git a/src/components/Dashboard/DashboardSidebar.svelte b/src/components/Dashboard/DashboardSidebar.svelte index 6faba0f8..d21db3e2 100644 --- a/src/components/Dashboard/DashboardSidebar.svelte +++ b/src/components/Dashboard/DashboardSidebar.svelte @@ -70,7 +70,7 @@ --> {#if benutzer.rolle === "ADMIN"} -
  • +
  • Admin @@ -80,6 +80,11 @@ Ausweise Prüfen
  • +
  • + + Impersonate User + +
  • {/if} diff --git a/src/modules/Dashboard/DashboardModule.svelte b/src/modules/Dashboard/DashboardModule.svelte index 16c4bec0..6f7fcd7e 100644 --- a/src/modules/Dashboard/DashboardModule.svelte +++ b/src/modules/Dashboard/DashboardModule.svelte @@ -93,6 +93,8 @@ objekte = objekte } let filters: { name: keyof z.infer, type: ZodTypeAny, value: any }[] = [] + + export let id: string = "";

    Gebäudeübersicht

    @@ -100,9 +102,13 @@
    {#if user.rolle === Enums.BenutzerRolle.ADMIN} -
    + +
    + + +
    {/if}
    diff --git a/src/modules/ImpersonateUserModule.svelte b/src/modules/ImpersonateUserModule.svelte new file mode 100644 index 00000000..8b623303 --- /dev/null +++ b/src/modules/ImpersonateUserModule.svelte @@ -0,0 +1,34 @@ + + + + +{#await userRequest} + +{:then users} +
    + {#each users as user} +
    +
    + {user.vorname} {user.name} + {user.email} +
    + Einloggen +
    + {/each} +
    +{/await} \ No newline at end of file diff --git a/src/pages/api/user/index.ts b/src/pages/api/user/index.ts index b33241eb..143cda6a 100644 --- a/src/pages/api/user/index.ts +++ b/src/pages/api/user/index.ts @@ -1,9 +1,10 @@ import { UUidWithPrefix } from "#components/Ausweis/types.js"; -import { authorizationMiddleware } from "#lib/middleware/authorization.js"; +import { adminMiddleware, authorizationMiddleware } from "#lib/middleware/authorization.js"; import { hashPassword } from "#lib/password.js"; import { sendRegisterMail } from "#lib/server/mail/registrierung.js"; -import { BenutzerSchema, prisma } from "#lib/server/prisma.js"; +import { prisma } from "#lib/server/prisma.js"; import { APIError, defineApiRoute } from "astro-typesafe-api/server"; +import { BenutzerSchema } from "src/generated/zod/benutzer.js"; import { z } from "zod"; export const POST = defineApiRoute({ @@ -40,6 +41,39 @@ export const POST = defineApiRoute({ }, }) +export const GET = defineApiRoute({ + input: z.object({ + uid: UUidWithPrefix + }).or(z.object({ + take: z.number(), + email: z.string() + })), + output: z.array(BenutzerSchema), + middleware: adminMiddleware, + async fetch(input, context, admin) { + if ("uid" in input) { + const user = await prisma.benutzer.findUnique({ + where: { + uid: input.uid + } + }) + + return [user]; + } else { + const users = await prisma.benutzer.findMany({ + where: { + email: { + startsWith: input.email + } + }, + take: input.take + }) + + return users; + } + }, +}) + export const PUT = defineApiRoute({ input: z.object({ email: z.string().email(), diff --git a/src/pages/dashboard/admin/impersonate-user.astro b/src/pages/dashboard/admin/impersonate-user.astro new file mode 100644 index 00000000..871346c1 --- /dev/null +++ b/src/pages/dashboard/admin/impersonate-user.astro @@ -0,0 +1,33 @@ +--- +import DashboardLayout from "#layouts/DashboardLayout.astro"; +import UserLayout from "#layouts/DashboardLayout.astro"; +import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants"; +import { Enums, prisma } from "#lib/server/prisma"; +import { createCaller } from "src/astro-typesafe-api-caller"; +import DashboardModule from "#modules/Dashboard/DashboardModule.svelte"; +import ImpersonateUserModule from "#modules/ImpersonateUserModule.svelte"; + +const caller = createCaller(Astro) + +const params = Astro.params; +const page = Number(params.page) + +const user = await caller.user.self.GET.fetch(undefined, { + headers: { + "Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` + } +}); + +if (!user) { + return Astro.redirect("/auth/login") +} + +if (user.rolle !== Enums.BenutzerRolle.ADMIN) { + return Astro.redirect("/dashboard") +} + +--- + + + + \ No newline at end of file diff --git a/src/pages/dashboard/admin/impersonate.astro b/src/pages/dashboard/admin/impersonate.astro new file mode 100644 index 00000000..62c2617c --- /dev/null +++ b/src/pages/dashboard/admin/impersonate.astro @@ -0,0 +1,66 @@ +--- +import { encodeToken } from "#lib/auth/token"; +import { TokenType } from "#lib/auth/types"; +import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME } from "#lib/constants"; +import { Enums, prisma } from "#lib/server/prisma"; +import moment from "moment"; +import { createCaller } from "src/astro-typesafe-api-caller"; + +const caller = createCaller(Astro) + +const user = await caller.user.self.GET.fetch(undefined, { + headers: { + "Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` + } +}); + +if (!user) { + return Astro.redirect("/auth/login") +} + +if (user.rolle !== Enums.BenutzerRolle.ADMIN) { + return Astro.redirect("/dashboard") +} + +const uid = Astro.url.searchParams.get("uid") + +if (!uid) { + return Astro.redirect("/404") +} + +const searchedUser = await prisma.benutzer.findUnique({ + where: { + uid + } +}) + +if (!searchedUser) { + return Astro.redirect("/dashboard/impersonate-user") +} + +const refreshTokenExpiry = moment().add(30, "days"); +const accessToken = encodeToken({ + uid: searchedUser.uid, + typ: TokenType.Access, + exp: moment().add(30, "minutes").valueOf(), +}); +const refreshToken = encodeToken({ + uid: searchedUser.uid, + typ: TokenType.Refresh, + exp: refreshTokenExpiry.valueOf(), +}); + +Astro.cookies.set(API_REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + domain: `.${Astro.url.hostname}`, + path: "/", + expires: refreshTokenExpiry.toDate() +}) +Astro.cookies.set(API_ACCESS_TOKEN_COOKIE_NAME, accessToken, { + domain: `.${Astro.url.hostname}`, + path: "/", + expires: moment().add(30, "minutes").toDate() +}) +Astro.cookies.set("uid", searchedUser.uid) + +return Astro.redirect("/dashboard") +--- \ No newline at end of file diff --git a/src/pages/dashboard/objekte/[page].astro b/src/pages/dashboard/objekte/[page].astro index 4e60590e..74d81b60 100644 --- a/src/pages/dashboard/objekte/[page].astro +++ b/src/pages/dashboard/objekte/[page].astro @@ -10,6 +10,9 @@ const caller = createCaller(Astro) const params = Astro.params; const page = Number(params.page) +const id = parseInt(Astro.url.searchParams.get("id") || "") + + const user = await caller.user.self.GET.fetch(undefined, { headers: { "Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` @@ -32,8 +35,76 @@ const objekte = await prisma.objekt.findMany({ where: user.rolle === Enums.BenutzerRolle.USER ? { benutzer: { uid: user.uid - } - } : {}, + }, + } : { + OR: [ + { + aufnahmen: { + some: { + verbrauchsausweise_gewerbe: { + some: { + alte_ausweis_id: id + } + }, + } + } + }, + { + aufnahmen: { + some: { + verbrauchsausweise_wohnen: { + some: { + alte_ausweis_id: id + } + }, + } + } + }, + { + aufnahmen: { + some: { + bedarfsausweise_wohnen: { + some: { + alte_ausweis_id: id + } + }, + } + } + }, + { + aufnahmen: { + some: { + verbrauchsausweise_gewerbe: { + some: { + id: id + } + }, + } + } + }, + { + aufnahmen: { + some: { + verbrauchsausweise_wohnen: { + some: { + id: id + } + }, + } + } + }, + { + aufnahmen: { + some: { + bedarfsausweise_wohnen: { + some: { + id: id + } + }, + } + } + },] + }, orderBy: { erstellungsdatum: "desc" }, @@ -53,6 +124,6 @@ const objekte = await prisma.objekt.findMany({ }) --- - - + + \ No newline at end of file diff --git a/src/pages/pdf/ansichtsausweis.ts b/src/pages/pdf/ansichtsausweis.ts index ba9694e4..028eb9bd 100644 --- a/src/pages/pdf/ansichtsausweis.ts +++ b/src/pages/pdf/ansichtsausweis.ts @@ -11,7 +11,7 @@ export const GET: APIRoute = async (Astro) => { const uidAusweis = Astro.url.searchParams.get("uid"); if (!uidAusweis) { - return Astro.redirect("/404") + return new Response(null, { status: 404 }); } const ausweisart = getAusweisartFromUUID(uidAusweis) @@ -46,7 +46,7 @@ export const GET: APIRoute = async (Astro) => { if (!ausweis) { - return Astro.redirect("/"); + return new Response(null, { status: 404 }); } aufnahme = await caller.aufnahme._uid.GET.fetch(undefined, { diff --git a/src/pages/pdf/datenblatt.ts b/src/pages/pdf/datenblatt.ts index ae1d5a0e..345a6516 100644 --- a/src/pages/pdf/datenblatt.ts +++ b/src/pages/pdf/datenblatt.ts @@ -13,7 +13,7 @@ export const GET: APIRoute = async (Astro) => { const uidAusweis = Astro.url.searchParams.get("uid"); if (!uidAusweis) { - return Astro.redirect("/404") + return new Response(null, { status: 404 }); } const ausweisart = getAusweisartFromUUID(uidAusweis) @@ -48,7 +48,7 @@ export const GET: APIRoute = async (Astro) => { if (!ausweis) { - return Astro.redirect("/"); + return new Response(null, { status: 404 }); } aufnahme = await caller.aufnahme._uid.GET.fetch(undefined, {