Bildupload und Kundendaten
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -13,7 +13,8 @@
|
|||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"build:production": "astro build && bun --bun server.ts",
|
"build:production": "astro build && bun --bun server.ts",
|
||||||
"i18n:generate": "bunx astro-i18next generate",
|
"i18n:generate": "bunx astro-i18next generate",
|
||||||
"prisma:studio": "bunx prisma studio --schema=./node_modules/@ibcornelsen/database/prisma/schema.prisma"
|
"prisma:studio": "bunx prisma studio --schema=./node_modules/@ibcornelsen/database/prisma/schema.prisma",
|
||||||
|
"openapi:generate": "bun astro-typesafe-api generate"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -43,6 +44,7 @@
|
|||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"js-interpolate": "^1.3.2",
|
"js-interpolate": "^1.3.2",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"jwt-decode": "^4.0.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"moment-timezone": "^0.5.46",
|
"moment-timezone": "^0.5.46",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
|
|||||||
BIN
persistent/images/3c319927-d226-4c84-8650-11bcc3d90670.webp
Normal file
BIN
persistent/images/3c319927-d226-4c84-8650-11bcc3d90670.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 MiB |
@@ -6,9 +6,9 @@ export const createCaller = createCallerFactory({
|
|||||||
"ticket": await import("../src/pages/api/ticket.ts"),
|
"ticket": await import("../src/pages/api/ticket.ts"),
|
||||||
"aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid].ts"),
|
"aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid].ts"),
|
||||||
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
||||||
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
|
||||||
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
||||||
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
||||||
|
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||||
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
||||||
"user": await import("../src/pages/api/user/index.ts"),
|
"user": await import("../src/pages/api/user/index.ts"),
|
||||||
"user/self": await import("../src/pages/api/user/self.ts"),
|
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME, API_UID_COOKIE_NAME } from "#lib/constants.js";
|
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME, API_UID_COOKIE_NAME } from "#lib/constants.js";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import jwt from "jsonwebtoken"
|
import { TokenData, TokenType } from "#lib/auth/types.js";
|
||||||
import { TokenData, TokenType } from "#lib/auth/token.js";
|
|
||||||
import { api } from "astro-typesafe-api/client";
|
import { api } from "astro-typesafe-api/client";
|
||||||
|
import { jwtDecode } from "jwt-decode"
|
||||||
|
|
||||||
|
|
||||||
export async function validateAccessTokenClient() {
|
export async function validateAccessTokenClient() {
|
||||||
@@ -11,9 +11,7 @@ export async function validateAccessTokenClient() {
|
|||||||
const refreshToken = Cookies.get(API_REFRESH_TOKEN_COOKIE_NAME);
|
const refreshToken = Cookies.get(API_REFRESH_TOKEN_COOKIE_NAME);
|
||||||
|
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
const { exp, typ, uid } = jwt.decode(accessToken, {
|
const { exp, typ, uid } = jwtDecode(accessToken) as TokenData
|
||||||
json: true
|
|
||||||
}) as TokenData
|
|
||||||
|
|
||||||
if (exp > Date.now() && typ === TokenType.Access) {
|
if (exp > Date.now() && typ === TokenType.Access) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
import { api } from "astro-typesafe-api/client"
|
import { api } from "astro-typesafe-api/client"
|
||||||
|
|
||||||
import { exclude } from "#lib/exclude.js";
|
import { exclude } from "#lib/exclude.js";
|
||||||
import { bilderHochladen } from "./bilderHochladen.js";
|
|
||||||
import { prisma } from "@ibcornelsen/database/server";
|
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||||
import { AufnahmeClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient, } from "#components/Ausweis/types.js";
|
import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient, } from "#components/Ausweis/types.js";
|
||||||
// import { addNotification } from "@ibcornelsen/ui";
|
// import { addNotification } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
export async function verbrauchsausweisWohnenSpeichern(
|
export async function verbrauchsausweisWohnenSpeichern(
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import AusweisWeiter from "#modules/VerbrauchsausweisWohnen/AusweisWeiter.svelte";
|
import AusweisWeiter from "#modules/VerbrauchsausweisWohnen/AusweisWeiter.svelte";
|
||||||
import Hilfe from "#components/Ausweis/Hilfe.svelte";
|
import Hilfe from "#components/Ausweis/Hilfe.svelte";
|
||||||
|
import { AufnahmeClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "./types.js";
|
||||||
|
|
||||||
export let ausweis;
|
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||||
export let images;
|
export let bilder: UploadedGebaeudeBild[];
|
||||||
export let user;
|
export let user: BenutzerClient;
|
||||||
export let gebaeude;
|
export let objekt: ObjektClient;
|
||||||
export let aufnahme;
|
export let aufnahme: AufnahmeClient;
|
||||||
|
|
||||||
export let spaeterWeitermachen;
|
export let spaeterWeitermachen;
|
||||||
|
|
||||||
@@ -26,9 +27,9 @@
|
|||||||
<div class="">
|
<div class="">
|
||||||
<AusweisWeiter
|
<AusweisWeiter
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
bind:images
|
bind:bilder
|
||||||
bind:user
|
bind:user
|
||||||
bind:gebaeude
|
bind:objekt
|
||||||
bind:aufnahme
|
bind:aufnahme
|
||||||
></AusweisWeiter>
|
></AusweisWeiter>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import AusweisWeiter from "#modules/VerbrauchsausweisWohnen/AusweisWeiter.svelte";
|
import AusweisWeiter from "#modules/VerbrauchsausweisWohnen/AusweisWeiter.svelte";
|
||||||
import Hilfe from "#components/Ausweis/Hilfe.svelte";
|
import Hilfe from "#components/Ausweis/Hilfe.svelte";
|
||||||
|
import { AufnahmeClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "./types.js";
|
||||||
|
|
||||||
export let ausweis;
|
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||||
export let images;
|
export let bilder: UploadedGebaeudeBild[];
|
||||||
export let user;
|
export let user: BenutzerClient;
|
||||||
export let gebaeude;
|
export let objekt: ObjektClient;
|
||||||
export let aufnahme;
|
export let aufnahme: AufnahmeClient;
|
||||||
|
|
||||||
export let spaeterWeitermachen;
|
export let spaeterWeitermachen;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
|
|
||||||
import ZipSearch from "#components/PlzSuche.svelte";
|
import ZipSearch from "#components/PlzSuche.svelte";
|
||||||
import { Enums } from "@ibcornelsen/database/client"
|
import { Enums } from "@ibcornelsen/database/client"
|
||||||
|
import { AufnahmeClient, ObjektClient } from "./types.js";
|
||||||
|
|
||||||
export let aufnahme: GebaeudeAufnahmeClient;
|
export let aufnahme: AufnahmeClient;
|
||||||
|
export let objekt: ObjektClient;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -29,7 +31,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
required
|
required
|
||||||
data-msg-minlength="min. 5 Zeichen"
|
data-msg-minlength="min. 5 Zeichen"
|
||||||
data-msg-maxlength="max. 40 Zeichen"
|
data-msg-maxlength="max. 40 Zeichen"
|
||||||
bind:value={aufnahme.adresse}
|
bind:value={objekt.adresse}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="help-label">
|
<div class="help-label">
|
||||||
@@ -47,8 +49,8 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
<Inputlabel title="PLZ *"></Inputlabel>
|
<Inputlabel title="PLZ *"></Inputlabel>
|
||||||
|
|
||||||
<ZipSearch
|
<ZipSearch
|
||||||
bind:zip={aufnahme.plz}
|
bind:zip={objekt.plz}
|
||||||
bind:city={aufnahme.ort}
|
bind:city={objekt.ort}
|
||||||
name="plz"
|
name="plz"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -61,7 +63,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
name="ort"
|
name="ort"
|
||||||
data-test="ort"
|
data-test="ort"
|
||||||
readonly={true}
|
readonly={true}
|
||||||
bind:value={aufnahme.ort}
|
bind:value={objekt.ort}
|
||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,34 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let bereich: string;
|
export let bereich: string;
|
||||||
export let title: string;
|
export let title: string;
|
||||||
export let bullets: string;
|
export let bullets: [string, boolean][];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="">
|
<div class="">
|
||||||
<strong>{bereich} - {title}</strong>
|
<strong>{bereich} - {title}</strong>
|
||||||
<div class="mt-4 mb-6">
|
<div class="mt-4 mb-6">
|
||||||
|
{#each bullets as [bullet, check]}
|
||||||
{#each bullets as [bullet, check]}
|
<div
|
||||||
<div class="bullets grid grid-cols-[1fr_40px] items-center border-b-[1px] border-b-black/10">
|
class="bullets grid grid-cols-[1fr_40px] items-center border-b-[1px] border-b-black/10"
|
||||||
|
>
|
||||||
<span>{@html bullet}</span>
|
<span>{@html bullet}</span>
|
||||||
<div class="justify-self-end" class:check={check} class:check-no={!check}>{check ? "✔" : "✘"}</div>
|
<div
|
||||||
|
class="justify-self-end"
|
||||||
|
class:check
|
||||||
|
class:check-no={!check}
|
||||||
|
>
|
||||||
|
{check ? "✔" : "✘"}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
|
.check {
|
||||||
.check{@apply self-center font-bold text-green-700}
|
@apply self-center font-bold text-green-700;
|
||||||
.check-no{@apply self-center font-bold text-red-700}
|
}
|
||||||
|
.check-no {
|
||||||
</style>
|
@apply self-center font-bold text-red-700;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -89,4 +89,18 @@ type ZodOverlapType<T> = z.ZodType<T, z.ZodTypeDef, T>;
|
|||||||
|
|
||||||
export function ZodOverlap<T, S = z.ZodType<T, z.ZodTypeDef, T>>(arg: S): S {
|
export function ZodOverlap<T, S = z.ZodType<T, z.ZodTypeDef, T>>(arg: S): S {
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PickNullable<T> = {
|
||||||
|
[P in keyof T as null extends T[P] ? P : never]: T[P]
|
||||||
|
}
|
||||||
|
|
||||||
|
type PickNotNullable<T> = {
|
||||||
|
[P in keyof T as null extends T[P] ? never : P]: T[P]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OptionalNullable<T> = T extends object ? {
|
||||||
|
[K in keyof PickNullable<T>]?: OptionalNullable<T[K]>
|
||||||
|
} & {
|
||||||
|
[K in keyof PickNotNullable<T>]: OptionalNullable<T[K]>
|
||||||
|
} : T;
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
|
import { TokenData } from "./types.js";
|
||||||
export enum TokenType {
|
|
||||||
Refresh,
|
|
||||||
Access,
|
|
||||||
Reset
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TokenData = { uid: string, typ: TokenType, exp: number }
|
|
||||||
|
|
||||||
export function encodeToken(data: TokenData) {
|
export function encodeToken(data: TokenData) {
|
||||||
const token = jwt.sign(data, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4", {
|
const token = jwt.sign(data, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4", {
|
||||||
|
|||||||
7
src/lib/auth/types.ts
Normal file
7
src/lib/auth/types.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export enum TokenType {
|
||||||
|
Refresh,
|
||||||
|
Access,
|
||||||
|
Reset
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TokenData = { uid: string, typ: TokenType, exp: number }
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
|
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
|
||||||
import ProgressBar from "#components/Ausweis/Progressbar.svelte";
|
import ProgressBar from "#components/Ausweis/Progressbar.svelte";
|
||||||
import Pruefung from "#components/Ausweis/Pruefung.svelte";
|
import Pruefung from "#components/Ausweis/Pruefung.svelte";
|
||||||
import ButtonZurueckSpeichernKaufabschluss from "#components/Ausweis/ButtonZurueckSpeichernKaufabschluss.svelte";
|
|
||||||
|
|
||||||
import type { Bezahlmethoden } from "@ibcornelsen/database/client";
|
import type { Bezahlmethoden } from "@ibcornelsen/database/client";
|
||||||
import { Enums } from "@ibcornelsen/database/client";
|
import { Enums } from "@ibcornelsen/database/client";
|
||||||
@@ -10,21 +9,17 @@
|
|||||||
import LoginDialog from "#components/LoginDialog.svelte";
|
import LoginDialog from "#components/LoginDialog.svelte";
|
||||||
import { PRICES } from "#lib/constants.js";
|
import { PRICES } from "#lib/constants.js";
|
||||||
import {
|
import {
|
||||||
|
AufnahmeClient,
|
||||||
BenutzerClient,
|
BenutzerClient,
|
||||||
|
ObjektClient,
|
||||||
VerbrauchsausweisWohnenClient,
|
VerbrauchsausweisWohnenClient,
|
||||||
} from "#components/Ausweis/types.js";
|
} from "#components/Ausweis/types.js";
|
||||||
import { validateAccessTokenClient } from "src/client/lib/validateAccessToken.js";
|
import { validateAccessTokenClient } from "src/client/lib/validateAccessToken.js";
|
||||||
import { client } from "src/trpc.js";
|
|
||||||
|
|
||||||
export let user: BenutzerClient;
|
export let user: BenutzerClient;
|
||||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||||
|
export let aufnahme: AufnahmeClient;
|
||||||
export let bereich;
|
export let objekt: ObjektClient;
|
||||||
export let title;
|
|
||||||
export let bullets;
|
|
||||||
|
|
||||||
let aufnahme = ausweis.aufnahme || {};
|
|
||||||
let gebaeude = ausweis.aufnahme?.objekt || {};
|
|
||||||
|
|
||||||
let services = [
|
let services = [
|
||||||
{
|
{
|
||||||
@@ -58,8 +53,8 @@
|
|||||||
|
|
||||||
let prices: number[] = [];
|
let prices: number[] = [];
|
||||||
|
|
||||||
if (ausweis.aufnahme.ausweisart) {
|
if (aufnahme.ausweisart) {
|
||||||
prices = PRICES[ausweis.aufnahme.ausweisart];
|
prices = PRICES[aufnahme.ausweisart];
|
||||||
}
|
}
|
||||||
|
|
||||||
let basePrice: number = prices[0];
|
let basePrice: number = prices[0];
|
||||||
@@ -71,7 +66,7 @@
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
async function speichern(e: MouseEvent) {
|
async function speichern(e: SubmitEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
|
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
|
||||||
@@ -102,8 +97,8 @@
|
|||||||
<div id="performance-box" class="w-full box relative px-4 order-2 2xl:order-1 self-stretch grid grid-cols-1">
|
<div id="performance-box" class="w-full box relative px-4 order-2 2xl:order-1 self-stretch grid grid-cols-1">
|
||||||
<PerformanceScore
|
<PerformanceScore
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
bind:aufnahme={aufnahme}
|
bind:aufnahme
|
||||||
bind:objekt={gebaeude}
|
bind:objekt
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -301,7 +296,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ButtonZurueckSpeichernKaufabschluss />
|
<!-- <ButtonZurueckSpeichernKaufabschluss bind:ausweis bind:aufnahme bind:objekt bind:bilder bind:user /> -->
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
import { api } from "astro-typesafe-api/client"
|
import { api } from "astro-typesafe-api/client"
|
||||||
|
|
||||||
export let objekt: ObjektClient;
|
export let objekt: ObjektClient;
|
||||||
export let images: UploadedGebaeudeBild[];
|
export let bilder: UploadedGebaeudeBild[];
|
||||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||||
export let user: BenutzerClient;
|
export let user: BenutzerClient;
|
||||||
export let aufnahme: AufnahmeClient;
|
export let aufnahme: AufnahmeClient;
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
const response = await verbrauchsausweisWohnenSpeichern(ausweis,
|
const response = await verbrauchsausweisWohnenSpeichern(ausweis,
|
||||||
objekt,
|
objekt,
|
||||||
aufnahme,
|
aufnahme,
|
||||||
images)
|
bilder)
|
||||||
|
|
||||||
if (response !== null) {
|
if (response !== null) {
|
||||||
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
|
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
|
||||||
@@ -43,6 +43,8 @@
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
console.log(e);
|
||||||
|
|
||||||
await api.ticket.PUT.fetch({
|
await api.ticket.PUT.fetch({
|
||||||
titel: "Ausweis konnte nicht gespeichert werden",
|
titel: "Ausweis konnte nicht gespeichert werden",
|
||||||
beschreibung: e.stack,
|
beschreibung: e.stack,
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ const ausweisart: Enums.Ausweisart = "VerbrauchsausweisWohnen"
|
|||||||
<Bereich
|
<Bereich
|
||||||
bereich="B"
|
bereich="B"
|
||||||
title="Eingabe der Gebäudeadresse - Angaben zu Wohnfläche, Keller und Dachgeschoss"
|
title="Eingabe der Gebäudeadresse - Angaben zu Wohnfläche, Keller und Dachgeschoss"
|
||||||
><GebaeudeDaten bind:aufnahme={aufnahme} /></Bereich
|
><GebaeudeDaten bind:aufnahme bind:objekt /></Bereich
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- C Eingabe von 3 zusammenhängenden Verbrauchsjahren -->
|
<!-- C Eingabe von 3 zusammenhängenden Verbrauchsjahren -->
|
||||||
@@ -296,10 +296,10 @@ const ausweisart: Enums.Ausweisart = "VerbrauchsausweisWohnen"
|
|||||||
|
|
||||||
<ButtonWeiterHilfe {spaeterWeitermachen}
|
<ButtonWeiterHilfe {spaeterWeitermachen}
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
bind:images={bilder}
|
bind:bilder
|
||||||
bind:user
|
bind:user
|
||||||
bind:gebaeude={objekt}
|
bind:objekt
|
||||||
bind:aufnahme={aufnahme}
|
bind:aufnahme
|
||||||
>
|
>
|
||||||
</ButtonWeiterHilfe>
|
</ButtonWeiterHilfe>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AufnahmeClient, ZodOverlap } from "#components/Ausweis/types.js";
|
import { AufnahmeClient, OptionalNullable, ZodOverlap } from "#components/Ausweis/types.js";
|
||||||
import { exclude } from "#lib/exclude.js";
|
import { exclude } from "#lib/exclude.js";
|
||||||
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
import { AufnahmeSchema, prisma } from "@ibcornelsen/database/server";
|
import { AufnahmeSchema, prisma } from "@ibcornelsen/database/server";
|
||||||
@@ -57,7 +57,7 @@ export const GET = defineApiRoute({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
output: ZodOverlap<AufnahmeClient>(AufnahmeSchema.omit({
|
output: ZodOverlap<OptionalNullable<AufnahmeClient>>(AufnahmeSchema.omit({
|
||||||
id: true,
|
id: true,
|
||||||
objekt_id: true,
|
objekt_id: true,
|
||||||
benutzer_id: true
|
benutzer_id: true
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const PUT = defineApiRoute({
|
|||||||
benutzer_id: true,
|
benutzer_id: true,
|
||||||
objekt_id: true,
|
objekt_id: true,
|
||||||
}).merge(z.object({
|
}).merge(z.object({
|
||||||
baujahr_klima: z.array(z.number().int().positive()).optional()
|
baujahr_klima: z.array(z.number().int().positive()).nullish()
|
||||||
})),
|
})),
|
||||||
uid_objekt: z.string().uuid()
|
uid_objekt: z.string().uuid()
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { prisma } from "@ibcornelsen/database/server";
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
import { TokenType, encodeToken } from "../../../lib/auth/token.js";
|
import { encodeToken } from "../../../lib/auth/token.js";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { defineApiRoute } from "astro-typesafe-api/server";
|
import { defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
import { TokenType } from "#lib/auth/types.js";
|
||||||
|
|
||||||
export const GET = defineApiRoute({
|
export const GET = defineApiRoute({
|
||||||
meta: {
|
meta: {
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { prisma } from "@ibcornelsen/database/server";
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
import { TokenType, encodeToken } from "../../../lib/auth/token.js";
|
import { encodeToken } from "../../../lib/auth/token.js";
|
||||||
import { hashPassword, validatePassword } from "../../../lib/password.js";
|
import { validatePassword } from "../../../lib/password.js";
|
||||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
import { TokenType } from "#lib/auth/types.js";
|
||||||
|
|
||||||
export const GET = defineApiRoute({
|
export const GET = defineApiRoute({
|
||||||
meta: {
|
meta: {
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
import { GebaeudeBilderSchema, prisma } from "@ibcornelsen/database/server";
|
import { GebaeudeBilderSchema, prisma } from "@ibcornelsen/database/server";
|
||||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
import { z } from "astro:content";
|
import { z } from "zod";
|
||||||
import isBase64 from "is-base64";
|
import isBase64 from "is-base64";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
import { writeFileSync } from "fs";
|
||||||
|
|
||||||
export const PUT = defineApiRoute({
|
export const PUT = defineApiRoute({
|
||||||
input: GebaeudeBilderSchema.pick({
|
input: GebaeudeBilderSchema.pick({
|
||||||
@@ -20,7 +22,7 @@ export const PUT = defineApiRoute({
|
|||||||
if (!isBase64(base64, { mimeRequired: true })) {
|
if (!isBase64(base64, { mimeRequired: true })) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message: "Das Bild ist nicht base64 kodiert.",
|
message: "Das Bild ist nicht base64.",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,15 +60,17 @@ export const PUT = defineApiRoute({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const filePath = `/persistent/images/${bild.uid}.webp`;
|
const filePath = fileURLToPath(new URL(`../../../../../persistent/images/${bild.uid}.webp`, import.meta.url));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Wir optimieren das Bild und konvertieren es in WebP
|
// Wir optimieren das Bild und konvertieren es in WebP
|
||||||
// TODO: Sharp scheint nicht zu funktionieren, wir müssen das nochmal testen
|
// TODO: Sharp scheint nicht zu funktionieren, wir müssen das nochmal testen
|
||||||
// const optimizedBuffer = await sharp(buffer).webp({ quality: 80 }).toArray();
|
// const optimizedBuffer = await sharp(buffer).webp({ quality: 80 }).toArray();
|
||||||
|
|
||||||
await Bun.write(filePath, buffer)
|
writeFileSync(filePath, buffer)
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
console.log(e);
|
||||||
|
|
||||||
// Bild wurde nicht gespeichert, wir löschen den Eintrag wieder
|
// Bild wurde nicht gespeichert, wir löschen den Eintrag wieder
|
||||||
await prisma.gebaeudeBilder.delete({
|
await prisma.gebaeudeBilder.delete({
|
||||||
where: {
|
where: {
|
||||||
@@ -97,7 +101,8 @@ export const GET = defineApiRoute({
|
|||||||
|
|
||||||
const objekt = await prisma.objekt.findUnique({
|
const objekt = await prisma.objekt.findUnique({
|
||||||
where: {
|
where: {
|
||||||
uid
|
uid,
|
||||||
|
benutzer_id: user.id
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
benutzer_id: true,
|
benutzer_id: true,
|
||||||
@@ -110,7 +115,7 @@ export const GET = defineApiRoute({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!objekt || objekt.benutzer_id !== user.id) {
|
if (!objekt) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "FORBIDDEN",
|
code: "FORBIDDEN",
|
||||||
message: "Objekt existiert nicht oder gehört einem anderen Benutzer."
|
message: "Objekt existiert nicht oder gehört einem anderen Benutzer."
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ObjektClient, ZodOverlap } from "#components/Ausweis/types.js";
|
import { ObjektClient, OptionalNullable, ZodOverlap } from "#components/Ausweis/types.js";
|
||||||
import { exclude } from "#lib/exclude.js";
|
import { exclude } from "#lib/exclude.js";
|
||||||
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
import { ObjektSchema, prisma } from "@ibcornelsen/database/server";
|
import { ObjektSchema, prisma } from "@ibcornelsen/database/server";
|
||||||
@@ -59,7 +59,7 @@ export const GET = defineApiRoute({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
output: ZodOverlap<ObjektClient>(ObjektSchema.omit({
|
output: ZodOverlap<OptionalNullable<ObjektClient>>(ObjektSchema.omit({
|
||||||
benutzer_id: true,
|
benutzer_id: true,
|
||||||
id: true
|
id: true
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { VerbrauchsausweisWohnenClient, ZodOverlap } from "#components/Ausweis/types.js";
|
import { OptionalNullable, VerbrauchsausweisWohnenClient, ZodOverlap } from "#components/Ausweis/types.js";
|
||||||
import { exclude } from "#lib/exclude.js";
|
import { exclude } from "#lib/exclude.js";
|
||||||
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
import { prisma, VerbrauchsausweisWohnenSchema } from "@ibcornelsen/database/server";
|
import { prisma, VerbrauchsausweisWohnenSchema } from "@ibcornelsen/database/server";
|
||||||
@@ -60,7 +60,7 @@ export const GET = defineApiRoute({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
output: ZodOverlap<VerbrauchsausweisWohnenClient>(VerbrauchsausweisWohnenSchema.merge(z.object({
|
output: ZodOverlap<OptionalNullable<VerbrauchsausweisWohnenClient>>(VerbrauchsausweisWohnenSchema.merge(z.object({
|
||||||
uid_aufnahme: z.string().uuid(),
|
uid_aufnahme: z.string().uuid(),
|
||||||
uid_objekt: z.string().uuid(),
|
uid_objekt: z.string().uuid(),
|
||||||
uid_benutzer: z.string().uuid().optional()
|
uid_benutzer: z.string().uuid().optional()
|
||||||
@@ -73,8 +73,12 @@ export const GET = defineApiRoute({
|
|||||||
async fetch(input, context, user) {
|
async fetch(input, context, user) {
|
||||||
const { uid } = context.params;
|
const { uid } = context.params;
|
||||||
|
|
||||||
console.log(uid);
|
if (!uid) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Missing uid in request params"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -3,30 +3,65 @@
|
|||||||
import KundendatenModule from "#modules/KundendatenModule.svelte";
|
import KundendatenModule from "#modules/KundendatenModule.svelte";
|
||||||
import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro";
|
import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro";
|
||||||
import { Enums } from "@ibcornelsen/database/client";
|
import { Enums } from "@ibcornelsen/database/client";
|
||||||
import { createCaller } from "#lib/caller";
|
import { createCaller } from "../astro-typesafe-api-caller";
|
||||||
|
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||||
|
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||||
|
|
||||||
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
|
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
|
||||||
const uid = Astro.url.searchParams.get("uid");
|
const uid = Astro.url.searchParams.get("uid");
|
||||||
|
const valid = await validateAccessTokenServer(Astro)
|
||||||
|
|
||||||
if (!uid) {
|
if (!uid || !valid) {
|
||||||
return Astro.redirect("/404");
|
return Astro.redirect("/404");
|
||||||
}
|
}
|
||||||
|
|
||||||
const caller = createCaller(Astro);
|
|
||||||
|
|
||||||
const ausweis = await caller.v1.verbrauchsausweisWohnen.get({
|
const caller = createCaller(Astro)
|
||||||
uid
|
|
||||||
|
const ausweis = await caller["verbrauchsausweis-wohnen"]._uid.GET.fetch(undefined, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
uid
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const user = await caller.v1.benutzer.self();
|
const aufnahme = await caller.aufnahme._uid.GET.fetch(undefined, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
uid: ausweis.uid_aufnahme
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const objekt = await caller.objekt._uid.GET.fetch(undefined, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
uid: aufnahme.uid_objekt
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = await caller.user.self.GET.fetch(undefined, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
aufnahme.ausweisart = "VerbrauchsausweisWohnen"
|
||||||
|
|
||||||
|
|
||||||
if (!ausweis) {
|
|
||||||
|
|
||||||
|
if (!ausweis || !user) {
|
||||||
return Astro.redirect("/404");
|
return Astro.redirect("/404");
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
||||||
<KundendatenModule user={user} ausweis={ausweis} selectedPaymentType={Enums.Bezahlmethoden.paypal} client:load></KundendatenModule>
|
<KundendatenModule {user} {ausweis} {objekt} {aufnahme} selectedPaymentType={Enums.Bezahlmethoden.paypal} client:load></KundendatenModule>
|
||||||
</AusweisLayout>
|
</AusweisLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { AstroGlobal } from "astro";
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { createCaller } from "../../astro-typesafe-api-caller.js"
|
import { createCaller } from "../../astro-typesafe-api-caller.js"
|
||||||
import jwt from "jsonwebtoken"
|
import jwt from "jsonwebtoken"
|
||||||
import { TokenData, TokenType } from "#lib/auth/token.js";
|
import { TokenData, TokenType } from "#lib/auth/types.js";
|
||||||
|
|
||||||
export async function validateAccessTokenServer(astro: AstroGlobal) {
|
export async function validateAccessTokenServer(astro: AstroGlobal) {
|
||||||
const accessToken = astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
|
const accessToken = astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
|
||||||
|
|||||||
Reference in New Issue
Block a user