Update Authentication + Build Script
This commit is contained in:
11
.github/workflows/cd.yml
vendored
11
.github/workflows/cd.yml
vendored
@@ -3,8 +3,6 @@ name: Node.js CD
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
pull_request:
|
|
||||||
branches: [ main ]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -19,9 +17,10 @@ jobs:
|
|||||||
password: "!2Zc727cI1"
|
password: "!2Zc727cI1"
|
||||||
port: 22
|
port: 22
|
||||||
script: |
|
script: |
|
||||||
cd /home/root/apps/online-energieausweis
|
cd ~/apps/online-energiausweis
|
||||||
|
git reset --hard HEAD
|
||||||
|
git clean -f -d
|
||||||
git pull origin main
|
git pull origin main
|
||||||
git status
|
git status
|
||||||
pnpm install --prod
|
pnpm install
|
||||||
pnpm run build
|
bash build.sh
|
||||||
pm2 restart online-energieausweis
|
|
||||||
|
|||||||
24
.github/workflows/ci.yml
vendored
24
.github/workflows/ci.yml
vendored
@@ -1,24 +0,0 @@
|
|||||||
# This workflow will do a clean install of node dependencies,
|
|
||||||
# build the source code and run tests across different versions of node
|
|
||||||
# For more information see:
|
|
||||||
# https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
||||||
|
|
||||||
name: Node.js CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [ main ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Use Node.js 12
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 19.x
|
|
||||||
- run: npm i
|
|
||||||
- run: npm run build --if-present
|
|
||||||
- run: npm test
|
|
||||||
18
.github/workflows/docker-image.yml
vendored
18
.github/workflows/docker-image.yml
vendored
@@ -1,18 +0,0 @@
|
|||||||
name: Docker Image CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Build the Docker image
|
|
||||||
run: docker build . --file Dockerfile --tag online-energieausweis:$(date +%s)
|
|
||||||
37
build.sh
Normal file
37
build.sh
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Define your environment variables here
|
||||||
|
APP_NAME="online-energiausweis"
|
||||||
|
APP_PORT=3000
|
||||||
|
DB_CONTAINER_NAME="database"
|
||||||
|
DB_NAME="main"
|
||||||
|
DB_USER="main"
|
||||||
|
DB_PASSWORD="hHMP8cd^N3SnzGRR"
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_VOLUME="postgres_data"
|
||||||
|
|
||||||
|
git_pull_force() {
|
||||||
|
git reset --hard HEAD
|
||||||
|
git clean -f -d
|
||||||
|
git pull origin main
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zuerst müssen wir neue Änderungen von GitHub pullen.
|
||||||
|
cd ~/apps/$APP_NAME
|
||||||
|
git_pull_force;
|
||||||
|
|
||||||
|
# Dann bauen wir das Docker Image unserer Application
|
||||||
|
cd ~/apps/$APP_NAME
|
||||||
|
docker stop $APP_NAME
|
||||||
|
docker rm $APP_NAME
|
||||||
|
docker build -t $APP_NAME .
|
||||||
|
|
||||||
|
# Danach machen wir ein Backup der Datenbank, falls bei der Migration etwas schiefgehen sollte.
|
||||||
|
cd ~/backups/
|
||||||
|
BACKUP_FILENAME="$(date +"%Y-%m-%d_%H-%M-%S").sql.gz"
|
||||||
|
docker exec -t $DB_CONTAINER_NAME pg_dumpall -c -U $DB_USER | gzip > $BACKUP_FILENAME
|
||||||
|
|
||||||
|
# Und starten unsere App wieder.
|
||||||
|
docker run -d --name $APP_NAME --link $DB_CONTAINER_NAME -p "$APP_PORT:80" -e DB_CONNECTION=postgresql://$DB_USER:$DB_PASSWORD@${DB_CONTAINER_NAME}:$DB_PORT/$DB_NAME -e DB_PORT=$DB_PORT $APP_NAME
|
||||||
|
|
||||||
|
# Das Backup lassen wir da, falls irgendwas schief gehen sollte.
|
||||||
@@ -3,16 +3,16 @@
|
|||||||
import { Gebaeude } from "src/lib/Gebaeude";
|
import { Gebaeude } from "src/lib/Gebaeude";
|
||||||
import HelpLabel from "~/components/HelpLabel.svelte";
|
import HelpLabel from "~/components/HelpLabel.svelte";
|
||||||
import { auditHeizungGebaeudeBaujahr } from "../Verbrauchsausweis/audits/HeizungGebaeudeBaujahr";
|
import { auditHeizungGebaeudeBaujahr } from "../Verbrauchsausweis/audits/HeizungGebaeudeBaujahr";
|
||||||
import { addNotification, deleteNotification } from "../Notifications/shared";
|
import { addNotification, deleteNotification } from "@ibcornelsen/ui";
|
||||||
import TagInput from "../TagInput.svelte";
|
import TagInput from "../TagInput.svelte";
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
export let gebaeude: Gebaeude;
|
export let gebaeude: Gebaeude;
|
||||||
|
|
||||||
// TODO: Das ist scheise
|
|
||||||
let tags = writable([]);
|
|
||||||
|
|
||||||
$: ausweis = gebaeude.ausweis || new Verbrauchsausweis();
|
$: ausweis = gebaeude.ausweis || new Verbrauchsausweis();
|
||||||
|
|
||||||
|
let baujahr = writable(gebaeude.baujahr);
|
||||||
|
let baujahrAnlage = writable(gebaeude.ausweis.baujahr_anlage);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="GRB">
|
<div class="GRB">
|
||||||
@@ -96,9 +96,7 @@
|
|||||||
deleteNotification("HEIZUNG_BAUJAHR")
|
deleteNotification("HEIZUNG_BAUJAHR")
|
||||||
}}
|
}}
|
||||||
className="{auditHeizungGebaeudeBaujahr(gebaeude) ? "linked" : ""}"
|
className="{auditHeizungGebaeudeBaujahr(gebaeude) ? "linked" : ""}"
|
||||||
required
|
bind:tags={baujahrAnlage}
|
||||||
autocomplete="off"
|
|
||||||
bind:tags
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -133,9 +131,7 @@
|
|||||||
deleteNotification("GEBAEUDE_BAUJAHR")
|
deleteNotification("GEBAEUDE_BAUJAHR")
|
||||||
}}
|
}}
|
||||||
className="{auditHeizungGebaeudeBaujahr(gebaeude) ? "linked" : ""}"
|
className="{auditHeizungGebaeudeBaujahr(gebaeude) ? "linked" : ""}"
|
||||||
required
|
bind:tags={baujahr}
|
||||||
autocomplete="off"
|
|
||||||
bind:tags
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
/>
|
/>
|
||||||
<div class="tooltip">
|
<div class="tooltip">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
<div id="arrow" class="invisible absolute h-3 w-3 bg-inherit before:visible before:absolute before:h-3 before:w-3 right-2 before:rotate-45 before:bg-inherit before:content-['']"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
@apply absolute left-0 translate-x-[-50%] max-w-[350px] w-max break-words invisible bg-white rounded-lg p-2 shadow-lg top-0 translate-y-[calc(-100%-8px)] transition-all duration-300 opacity-0;
|
@apply absolute -right-1 max-w-[350px] w-max break-words invisible bg-white rounded-lg p-2 shadow-lg top-0 translate-y-[calc(-100%-8px)] transition-all duration-300 opacity-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-opener:hover .tooltip {
|
.tooltip-opener:hover .tooltip {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import cookie from "cookiejs";
|
import cookie from "cookiejs";
|
||||||
import { addNotification } from "./Notifications/shared";
|
import { addNotification } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
let email: string;
|
let email: string;
|
||||||
let password: string;
|
let password: string;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { addNotification } from "./Notifications/shared";
|
import { addNotification } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
let passwort: string;
|
let passwort: string;
|
||||||
let email: string;
|
let email: string;
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
let tag = "";
|
let tag = "";
|
||||||
|
|
||||||
export let tags: Writable<string[]> = writable([]);
|
export let tags: Writable<any[]> = writable([]);
|
||||||
export let addKeys: number[] = [13];
|
export let addKeys: number[] = [13, 32];
|
||||||
export let maxTags: number;
|
export let maxTags: number = Infinity;
|
||||||
export let onlyUnique: boolean = false;
|
export let onlyUnique: boolean = false;
|
||||||
export let removeKeys: number[] = [8];
|
export let removeKeys: number[] = [8];
|
||||||
export let placeholder: string = "";
|
export let placeholder: string = "";
|
||||||
@@ -13,26 +13,26 @@
|
|||||||
export let allowDrop: boolean = false;
|
export let allowDrop: boolean = false;
|
||||||
export let splitWith: string = ",";
|
export let splitWith: string = ",";
|
||||||
export let name: string = "";
|
export let name: string = "";
|
||||||
export let id: string = "";
|
|
||||||
export let allowBlur: boolean = true;
|
|
||||||
export let disable: boolean = false;
|
export let disable: boolean = false;
|
||||||
export let minChars: number = 0;
|
export let minChars: number = 0;
|
||||||
export let labelText;
|
|
||||||
export let labelShow;
|
|
||||||
export let readonly: boolean = false;
|
export let readonly: boolean = false;
|
||||||
export let onTagClick: Function;
|
export let onTagClick: Function = ()=>{};
|
||||||
export let onFocusIn: () => any;
|
export let onFocusIn: () => any = () => {};
|
||||||
export let onFocusOut: () => any;
|
export let onFocusOut: () => any = () => {};
|
||||||
export let className: string;
|
export let className: string = "";
|
||||||
|
|
||||||
function addTag(tag: string) {
|
function addTag(tag: string) {
|
||||||
if (onlyUnique && $tags.indexOf(tag) > -1) {
|
if ((onlyUnique && $tags.indexOf(tag) > -1) || maxTags == $tags.length) {
|
||||||
tag = "";
|
tag = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minChars > tag.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tags.update(value => {
|
tags.update(value => {
|
||||||
return [...value, tag];
|
return [...value, tag].sort((a,b) => a-b);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,8 @@
|
|||||||
on:focusin={onFocusIn}
|
on:focusin={onFocusIn}
|
||||||
on:focusout={onFocusOut}
|
on:focusout={onFocusOut}
|
||||||
class="border-none h-full w-full {className}"
|
class="border-none h-full w-full {className}"
|
||||||
disabled={disable || readonly}
|
disabled={disable}
|
||||||
|
readonly={readonly}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -11,10 +11,8 @@
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import BilderZusatzsysteme from "../Ausweis/BilderZusatzsysteme.svelte";
|
import BilderZusatzsysteme from "../Ausweis/BilderZusatzsysteme.svelte";
|
||||||
import { Gebaeude } from "src/lib/Gebaeude";
|
import { Gebaeude } from "src/lib/Gebaeude";
|
||||||
import { hideLinkedElement, notifications } from "../Notifications/shared";
|
|
||||||
import { gebaeude } from "./shared";
|
import { gebaeude } from "./shared";
|
||||||
import RawNotificationWrapper from "../Notifications/RawNotificationWrapper.svelte";
|
import { RawNotificationWrapper, RawNotification, notifications } from "@ibcornelsen/ui";
|
||||||
import RawNotification from "../Notifications/RawNotification.svelte";
|
|
||||||
import { auditHeizungGebaeudeBaujahr } from "./audits/HeizungGebaeudeBaujahr";
|
import { auditHeizungGebaeudeBaujahr } from "./audits/HeizungGebaeudeBaujahr";
|
||||||
import { AuditType, hidden } from "./audits/hidden";
|
import { AuditType, hidden } from "./audits/hidden";
|
||||||
import { auditBedarfsausweisBenoetigt } from "./audits/BedarfsausweisBenoetigt";
|
import { auditBedarfsausweisBenoetigt } from "./audits/BedarfsausweisBenoetigt";
|
||||||
@@ -26,9 +24,9 @@
|
|||||||
$gebaeude.ausweis = new Verbrauchsausweis();
|
$gebaeude.ausweis = new Verbrauchsausweis();
|
||||||
$gebaeude.ausweis.gebaeude = $gebaeude;
|
$gebaeude.ausweis.gebaeude = $gebaeude;
|
||||||
if (uid) {
|
if (uid) {
|
||||||
(async () => {
|
async () => {
|
||||||
const result = await fetch(`/api/verbrauchsausweis?uid=${uid}`, {
|
const result = await fetch(`/api/verbrauchsausweis?uid=${uid}`, {
|
||||||
method: "GET"
|
method: "GET",
|
||||||
});
|
});
|
||||||
|
|
||||||
const json = await result.json();
|
const json = await result.json();
|
||||||
@@ -38,14 +36,14 @@
|
|||||||
$gebaeude.ausweis = new Verbrauchsausweis(json.data.ausweis);
|
$gebaeude.ausweis = new Verbrauchsausweis(json.data.ausweis);
|
||||||
$gebaeude.ausweis.gebaeude = $gebaeude;
|
$gebaeude.ausweis.gebaeude = $gebaeude;
|
||||||
}
|
}
|
||||||
})
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
$: ausweis = $gebaeude.ausweis || new Verbrauchsausweis();
|
$: ausweis = $gebaeude.ausweis || new Verbrauchsausweis();
|
||||||
|
|
||||||
function automatischAusfüllen() {
|
function automatischAusfüllen() {
|
||||||
$gebaeude.baujahr = 1962;
|
$gebaeude.baujahr = [1962];
|
||||||
ausweis.baujahr_anlage = 1952;
|
ausweis.baujahr_anlage = [1952];
|
||||||
$gebaeude.saniert = true;
|
$gebaeude.saniert = true;
|
||||||
$gebaeude.einheiten = 1;
|
$gebaeude.einheiten = 1;
|
||||||
ausweis.ausstellgrund = "Vermietung";
|
ausweis.ausstellgrund = "Vermietung";
|
||||||
@@ -224,7 +222,8 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="IGwwbool"
|
class="IGwwbool"
|
||||||
name="IGwwbool"
|
name="IGwwbool"
|
||||||
bind:checked={ausweis.kennwerte.warmwasser_enthalten}
|
bind:checked={ausweis.kennwerte
|
||||||
|
.warmwasser_enthalten}
|
||||||
/>Warmwasser im Verbrauch enthalten</label
|
/>Warmwasser im Verbrauch enthalten</label
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -451,61 +450,72 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<RawNotificationWrapper>
|
<RawNotificationWrapper>
|
||||||
|
|
||||||
{#each Object.entries($notifications) as [uid, notification] (uid)}
|
{#each Object.entries($notifications) as [uid, notification] (uid)}
|
||||||
<RawNotification notification={{...notification, uid }}>
|
<RawNotification notification={{ ...notification, uid }}>
|
||||||
{@html notification.subtext}
|
{@html notification.subtext}
|
||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
{#if auditBedarfsausweisBenoetigt($gebaeude)}
|
{#if auditBedarfsausweisBenoetigt($gebaeude)}
|
||||||
<RawNotification notification={{
|
<RawNotification
|
||||||
message: "Bedarfsausweis benötigt!",
|
notification={{
|
||||||
timeout: 0,
|
message: "Bedarfsausweis benötigt!",
|
||||||
uid: "BEDARFSAUSWEIS",
|
timeout: 0,
|
||||||
dismissable: false,
|
uid: "BEDARFSAUSWEIS",
|
||||||
type: "info"
|
dismissable: false,
|
||||||
}}>
|
type: "info",
|
||||||
Sie benötigen einen Bedarfsausweis. <a href='/bedarfsausweis'>Bitte führen Sie hier Ihre Eingabe für den Bedarfsausweis fort</a>.
|
}}
|
||||||
|
>
|
||||||
|
Sie benötigen einen Bedarfsausweis. <a href="/bedarfsausweis"
|
||||||
|
>Bitte führen Sie hier Ihre Eingabe für den Bedarfsausweis fort</a
|
||||||
|
>.
|
||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if auditHeizungGebaeudeBaujahr($gebaeude)}
|
{#if auditHeizungGebaeudeBaujahr($gebaeude)}
|
||||||
<RawNotification notification={{
|
<RawNotification
|
||||||
message: "Plausibilitätsprüfung",
|
notification={{
|
||||||
timeout: 0,
|
message: "Plausibilitätsprüfung",
|
||||||
uid: "HEIZUNG_VOR_GEBAEUDE",
|
timeout: 0,
|
||||||
dismissable: true,
|
uid: "HEIZUNG_VOR_GEBAEUDE",
|
||||||
onUserDismiss: () => {
|
dismissable: true,
|
||||||
hidden.add(AuditType.HEIZUNG_GEBAEUDE_BAUJAHR)
|
onUserDismiss: () => {
|
||||||
$gebaeude = $gebaeude;
|
hidden.add(AuditType.HEIZUNG_GEBAEUDE_BAUJAHR);
|
||||||
},
|
$gebaeude = $gebaeude;
|
||||||
type: "warning"
|
},
|
||||||
}}>
|
type: "warning",
|
||||||
Sie haben angegeben, dass ihre Heizung vor ihrem Gebäude konstruiert wurde. Sind sie sich sicher, dass das stimmt?
|
}}
|
||||||
|
>
|
||||||
|
Sie haben angegeben, dass ihre Heizung vor ihrem Gebäude konstruiert
|
||||||
|
wurde. Sind sie sich sicher, dass das stimmt?
|
||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if auditVerbrauchAbweichung($gebaeude).length > 0}
|
{#if auditVerbrauchAbweichung($gebaeude).length > 0}
|
||||||
<RawNotification notification={{
|
<RawNotification
|
||||||
message: "Plausibilitätsprüfung",
|
notification={{
|
||||||
timeout: 0,
|
message: "Plausibilitätsprüfung",
|
||||||
uid: "VERBRAUCH_ABWEICHUNG",
|
timeout: 0,
|
||||||
dismissable: true,
|
uid: "VERBRAUCH_ABWEICHUNG",
|
||||||
onUserDismiss: () => {
|
dismissable: true,
|
||||||
hidden.add(AuditType.VERBRAUCH_ABWEICHUNG)
|
onUserDismiss: () => {
|
||||||
$gebaeude = $gebaeude;
|
hidden.add(AuditType.VERBRAUCH_ABWEICHUNG);
|
||||||
},
|
$gebaeude = $gebaeude;
|
||||||
type: "warning"
|
},
|
||||||
}}>
|
type: "warning",
|
||||||
Die Abweichung der Verbräuche zwischen Zeitraum {auditVerbrauchAbweichung($gebaeude)[0]} und {auditVerbrauchAbweichung($gebaeude)[1]} beträgt mehr als 25% und sie haben keinen Leerstand angegeben. Sind sie sich sicher, dass das stimmt?
|
}}
|
||||||
</RawNotification>
|
>
|
||||||
|
Die Abweichung der Verbräuche zwischen Zeitraum {auditVerbrauchAbweichung(
|
||||||
|
$gebaeude
|
||||||
|
)[0]} und {auditVerbrauchAbweichung($gebaeude)[1]} beträgt mehr als 25%
|
||||||
|
und sie haben keinen Leerstand angegeben. Sind sie sich sicher, dass
|
||||||
|
das stimmt?
|
||||||
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</RawNotificationWrapper>
|
</RawNotificationWrapper>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:global(.linked) {
|
:global(.linked) {
|
||||||
@apply border-2 border-red-400;
|
@apply border-2 border-red-400;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function auditHeizungGebaeudeBaujahr(gebaeude: Gebaeude): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ausweis.baujahr_anlage > 1500 &&
|
return ausweis.baujahr_anlage[0] > 1500 &&
|
||||||
gebaeude.baujahr > 1500 &&
|
gebaeude.baujahr[0] > 1500 &&
|
||||||
ausweis.baujahr_anlage < gebaeude.baujahr
|
ausweis.baujahr_anlage[0] < gebaeude.baujahr[0]
|
||||||
&& !hidden.has(AuditType.HEIZUNG_GEBAEUDE_BAUJAHR)
|
&& !hidden.has(AuditType.HEIZUNG_GEBAEUDE_BAUJAHR)
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,10 @@
|
|||||||
|
|
||||||
async function fetchZipCodeInformation() {
|
async function fetchZipCodeInformation() {
|
||||||
const result = await fetch(`/api/zip?zip=${zip}`, {
|
const result = await fetch(`/api/zip?zip=${zip}`, {
|
||||||
method: "GET"
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"authorization": "Basic " + btoa("user@ib-cornelsen.de:test")
|
||||||
|
}
|
||||||
}).then(r => r.json());
|
}).then(r => r.json());
|
||||||
|
|
||||||
if (result.success === true) {
|
if (result.success === true) {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import "../style/global.scss"
|
|||||||
import Footer from '../components/Footer.astro';
|
import Footer from '../components/Footer.astro';
|
||||||
import Header from '../components/Header.astro';
|
import Header from '../components/Header.astro';
|
||||||
import SidebarLeft from '../components/SidebarLeft.astro';
|
import SidebarLeft from '../components/SidebarLeft.astro';
|
||||||
import NotificationWrapper from "~/components/Notifications/NotificationWrapper.svelte";
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
import "../style/global.scss"
|
import "../style/global.scss";
|
||||||
import Footer from '../components/Footer.astro';
|
import Footer from "../components/Footer.astro";
|
||||||
import Header from '../components/Header.astro';
|
import Header from "../components/Header.astro";
|
||||||
import SidebarLeft from '../components/SidebarLeft.astro';
|
import SidebarLeft from "../components/SidebarLeft.astro";
|
||||||
import SidebarRight from '../components/SidebarRight.astro';
|
import SidebarRight from "../components/SidebarRight.astro";
|
||||||
import NotificationWrapper from "~/components/Notifications/NotificationWrapper.svelte";
|
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -13,27 +13,27 @@ export interface Props {
|
|||||||
const { title } = Astro.props;
|
const { title } = Astro.props;
|
||||||
|
|
||||||
const schema = JSON.stringify({
|
const schema = JSON.stringify({
|
||||||
'@context': 'http://schema.org',
|
"@context": "http://schema.org",
|
||||||
'@type': 'Corporation',
|
"@type": "Corporation",
|
||||||
name: 'IB Cornelsen',
|
name: "IB Cornelsen",
|
||||||
alternateName: 'online-energieausweis.org',
|
alternateName: "online-energieausweis.org",
|
||||||
url: 'https://online-energieausweis.org',
|
url: "https://online-energieausweis.org",
|
||||||
logo: 'https://online-energieausweis.org/ib-cornelsen.png',
|
logo: "https://online-energieausweis.org/ib-cornelsen.png",
|
||||||
address: {
|
address: {
|
||||||
'@type': 'PostalAddress',
|
"@type": "PostalAddress",
|
||||||
streetAddress: 'Katendeich 5A',
|
streetAddress: "Katendeich 5A",
|
||||||
addressLocality: 'Hamburg',
|
addressLocality: "Hamburg",
|
||||||
postalCode: '21035',
|
postalCode: "21035",
|
||||||
addressCountry: 'Deutschland',
|
addressCountry: "Deutschland",
|
||||||
email: 'info@online-energieausweis.org',
|
email: "info@online-energieausweis.org",
|
||||||
},
|
},
|
||||||
contactPoint: {
|
contactPoint: {
|
||||||
'@type': 'ContactPoint',
|
"@type": "ContactPoint",
|
||||||
telephone: '+49-040-209339850',
|
telephone: "+49-040-209339850",
|
||||||
faxNumber: '+49-040-209339859',
|
faxNumber: "+49-040-209339859",
|
||||||
contactType: 'customer service',
|
contactType: "customer service",
|
||||||
areaServed: 'DE',
|
areaServed: "DE",
|
||||||
availableLanguage: 'German',
|
availableLanguage: "German",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
---
|
---
|
||||||
@@ -65,7 +65,10 @@ const schema = JSON.stringify({
|
|||||||
content="✅ Jetzt Ihren Energieausweis online erstellen. Erhalten Sie Ihren online Energieausweis rechtssicher und nach aktueller GEG (vormals EnEV) vom Diplom Ingenieur geprüft."
|
content="✅ Jetzt Ihren Energieausweis online erstellen. Erhalten Sie Ihren online Energieausweis rechtssicher und nach aktueller GEG (vormals EnEV) vom Diplom Ingenieur geprüft."
|
||||||
/>
|
/>
|
||||||
<meta property="og:url" content="https://online-energieausweis.org/" />
|
<meta property="og:url" content="https://online-energieausweis.org/" />
|
||||||
<meta property="og:site_name" content="Energieausweis online erstellen" />
|
<meta
|
||||||
|
property="og:site_name"
|
||||||
|
content="Energieausweis online erstellen"
|
||||||
|
/>
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
<meta
|
<meta
|
||||||
@@ -81,21 +84,23 @@ const schema = JSON.stringify({
|
|||||||
content="https://online-energieausweis.org/images/energieausweis-online-erstellen.jpg"
|
content="https://online-energieausweis.org/images/energieausweis-online-erstellen.jpg"
|
||||||
/>
|
/>
|
||||||
<title>
|
<title>
|
||||||
{title || 'Energieausweis online erstellen - Online Energieausweis'}
|
{title || "Energieausweis online erstellen - Online Energieausweis"}
|
||||||
</title>
|
</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<Header />
|
<Header />
|
||||||
<main class="grid gap-6 p-6 grid-cols-[2fr,6fr,2fr] max-w-[1920px] w-full">
|
<main
|
||||||
<SidebarLeft></SidebarLeft>
|
class="grid gap-6 p-6 grid-cols-[2fr,6fr,2fr] max-w-[1920px] w-full"
|
||||||
|
>
|
||||||
|
<SidebarLeft />
|
||||||
<article class="mainContent">
|
<article class="mainContent">
|
||||||
<slot />
|
<slot />
|
||||||
</article>
|
</article>
|
||||||
<SidebarRight></SidebarRight>
|
<SidebarRight />
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
<NotificationWrapper client:load></NotificationWrapper>
|
<NotificationWrapper client:load />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
@@ -117,7 +122,8 @@ const schema = JSON.stringify({
|
|||||||
@apply py-1.5 px-4 w-full rounded-lg outline-none text-lg text-slate-700 border bg-gray-50 transition-colors;
|
@apply py-1.5 px-4 w-full rounded-lg outline-none text-lg text-slate-700 border bg-gray-50 transition-colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:hover, input:focus {
|
input:hover,
|
||||||
|
input:focus {
|
||||||
@apply bg-gray-100;
|
@apply bg-gray-100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class Bedarfsausweis {
|
|||||||
public objekt_gebaeudeteil: string = "";
|
public objekt_gebaeudeteil: string = "";
|
||||||
public objekt_saniert: boolean = false;
|
public objekt_saniert: boolean = false;
|
||||||
public baujahr_gebaeude: number = 0;
|
public baujahr_gebaeude: number = 0;
|
||||||
public baujahr_anlage: number = 0;
|
public baujahr_anlage: number[] = [];
|
||||||
public anzahl_einheiten: number = 0;
|
public anzahl_einheiten: number = 0;
|
||||||
|
|
||||||
public erstellungsdatum: Date = new Date();
|
public erstellungsdatum: Date = new Date();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class VerbrauchsausweisGewerbe {
|
|||||||
public objekt_gebaeudeteil: string = "";
|
public objekt_gebaeudeteil: string = "";
|
||||||
public objekt_saniert: boolean = false;
|
public objekt_saniert: boolean = false;
|
||||||
public baujahr_gebaeude: number = 0;
|
public baujahr_gebaeude: number = 0;
|
||||||
public baujahr_anlage: number = 0;
|
public baujahr_anlage: number[] = [];
|
||||||
public anzahl_einheiten: number = 0;
|
public anzahl_einheiten: number = 0;
|
||||||
|
|
||||||
public erstellungsdatum: Date = new Date();
|
public erstellungsdatum: Date = new Date();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
import { Ausweis } from "./Ausweis/Ausweis";
|
import { Ausweis } from "./Ausweis/Ausweis";
|
||||||
import { Verbrauchsausweis } from "./Ausweis/Verbrauchsausweis";
|
|
||||||
import { Dachgeschoss, Lueftungskonzept } from "./Ausweis/types";
|
import { Dachgeschoss, Lueftungskonzept } from "./Ausweis/types";
|
||||||
import { BitChecker } from "./BitChecker";
|
import { BitChecker } from "./BitChecker";
|
||||||
|
|
||||||
@@ -11,7 +10,7 @@ export class Gebaeude {
|
|||||||
public strasse: string = "";
|
public strasse: string = "";
|
||||||
public gebaeudeteil: string = "";
|
public gebaeudeteil: string = "";
|
||||||
public saniert: boolean = false;
|
public saniert: boolean = false;
|
||||||
public baujahr: number = 0;
|
public baujahr: number[] = [];
|
||||||
public einheiten: number = 0;
|
public einheiten: number = 0;
|
||||||
public wohnflaeche: number = 0;
|
public wohnflaeche: number = 0;
|
||||||
public keller_beheizt: boolean = false;
|
public keller_beheizt: boolean = false;
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ export function encodeToken(data: Record<string, any>) {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeToken(token: string) {
|
export function decodeToken<T>(token: string): Partial<T> {
|
||||||
return jwt.decode(token, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4");
|
return jwt.decode(token, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4");
|
||||||
}
|
}
|
||||||
1
src/lib/server/Authorization/index.ts
Normal file
1
src/lib/server/Authorization/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { validateAuthorizationHeader } from "./validate";
|
||||||
62
src/lib/server/Authorization/validate.ts
Normal file
62
src/lib/server/Authorization/validate.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { decodeToken } from "src/lib/JsonWebToken";
|
||||||
|
import { validatePassword } from "src/lib/Password";
|
||||||
|
import { User } from "src/lib/User";
|
||||||
|
|
||||||
|
export async function validateAuthorizationHeader(
|
||||||
|
request: Request,
|
||||||
|
validAuthenticationMethods: ("Bearer" | "Basic")[]
|
||||||
|
): Promise<User | null> {
|
||||||
|
if (!request.headers.has("authorization")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = request.headers.get("authorization") as string;
|
||||||
|
|
||||||
|
const [authorizationType, value] = header.split(" ");
|
||||||
|
|
||||||
|
if (authorizationType == "Basic" && validAuthenticationMethods.indexOf("Basic") > -1) {
|
||||||
|
// Basic user validation;
|
||||||
|
try {
|
||||||
|
const [email, password] = Buffer.from(value, "base64")
|
||||||
|
.toString()
|
||||||
|
.split(":");
|
||||||
|
const user = await User.fromEmail(email);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validatePassword(user.passwort, password)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (authorizationType == "Bearer" && validAuthenticationMethods.indexOf("Bearer") > -1) {
|
||||||
|
const stringToken = Buffer.from(value, "base64").toString();
|
||||||
|
try {
|
||||||
|
const token = decodeToken<{ id: number; uid: string; exp: string }>(
|
||||||
|
stringToken
|
||||||
|
);
|
||||||
|
const id = token.id;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = User.fromPrivateId(id);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/pages/api/token.ts
Normal file
34
src/pages/api/token.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import type { APIRoute } from "astro";
|
||||||
|
import { success, MissingPropertyError, error } from "../../lib/APIResponse";
|
||||||
|
import { validatePassword, hashPassword } from "../../lib/Password";
|
||||||
|
import { User } from "../../lib/User";
|
||||||
|
import moment from "moment";
|
||||||
|
import { encodeToken } from "../../lib/JsonWebToken";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ruft einen Nutzer anhand seiner uid aus der Datenbank ab.
|
||||||
|
* @param param0 Die Request mit dem request body. Dieser enthält entweder eine uid mit der der Benutzer identifiziert werden kann.
|
||||||
|
*/
|
||||||
|
export const post: APIRoute = async ({ request }) => {
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
if (!body.hasOwnProperty("email") || !body.hasOwnProperty("password")) {
|
||||||
|
return MissingPropertyError(["email", "password"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await User.fromEmail(body.email);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return error(["Invalid email or password."]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate Password
|
||||||
|
if (!validatePassword(user.passwort, body.password)) {
|
||||||
|
return error(["Invalid email or password."]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const expiry = moment().add(2, "days").unix();
|
||||||
|
const token = encodeToken({ id: user.id, uid: user.uid, exp: expiry })
|
||||||
|
|
||||||
|
return success({ token, expires: expiry });
|
||||||
|
}
|
||||||
@@ -1,12 +1,19 @@
|
|||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import { success, MissingPropertyError, MissingEntityError, InvalidDataError } from "../../lib/APIResponse";
|
import { success, MissingPropertyError, MissingEntityError, InvalidDataError, error } from "../../lib/APIResponse";
|
||||||
import { ZIPInformation } from "src/lib/ZIPInformation";
|
import { ZIPInformation } from "src/lib/ZIPInformation";
|
||||||
|
import { validateAuthorizationHeader } from "src/lib/server/Authorization";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ruft einen Nutzer anhand seiner uid aus der Datenbank ab.
|
* Ruft einen Nutzer anhand seiner uid aus der Datenbank ab.
|
||||||
* @param param0 Die Request mit dem request body. Dieser enthält entweder eine uid mit der der Benutzer identifiziert werden kann.
|
* @param param0 Die Request mit dem request body. Dieser enthält entweder eine uid mit der der Benutzer identifiziert werden kann.
|
||||||
*/
|
*/
|
||||||
export const get: APIRoute = async ({ request }) => {
|
export const get: APIRoute = async ({ request }) => {
|
||||||
|
const user = await validateAuthorizationHeader(request, ["Bearer", "Basic"]);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return error(["Invalid authentication credentials!"]);
|
||||||
|
}
|
||||||
|
|
||||||
const body = Object.fromEntries(new URLSearchParams(request.url.split("?")[1]))
|
const body = Object.fromEntries(new URLSearchParams(request.url.split("?")[1]))
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
|
|||||||
Reference in New Issue
Block a user