diff --git a/Makefile b/Makefile index 43cbc7b..9711355 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,18 @@ # ============================================================== # VEREINS.HAUS — Makefile # Deploy-Strategie: SSH zur DS, Docker Compose +# Stack: SvelteKit + better-sqlite3 (kein PocketBase) # ============================================================== DS_HOST := ds DS_IP := 10.47.11.10 DS_SSH_PORT := 4711 DS_PATH := /volume1/docker/vereinshaus -CONTAINER_PB := vereinshaus-pocketbase CONTAINER_APP := vereinshaus-app DOCKER := sudo /usr/local/bin/docker -STAGING_PATH := /volume1/docker/vereinshaus-staging -CONTAINER_PB_STAGING := vereinshaus-staging-pocketbase -CONTAINER_APP_STAGING:= vereinshaus-staging-app -STAGING_PB_URL := http://localhost:8091 -STAGING_MIGRATIONS := $(STAGING_PATH)/pocketbase/migrations -STAGING_HOOKS := $(STAGING_PATH)/pocketbase/data/pb_hooks +STAGING_PATH := /volume1/docker/vereinshaus-staging +CONTAINER_APP_STAGING := vereinshaus-staging-app TAR_EXCLUDE := --exclude='.git' \ --exclude='./app/node_modules' \ @@ -25,13 +21,8 @@ TAR_EXCLUDE := --exclude='.git' \ --exclude='./.env' \ --exclude='./.DS_Store' -HOOKS_SRC := pocketbase/pb_hooks -HOOKS_DST := /volume1/docker/vereinshaus/pocketbase/data/pb_hooks -MIGRATIONS_SRC := pocketbase/pb_migrations -MIGRATIONS_DST := /volume1/docker/vereinshaus/pocketbase/migrations - -.PHONY: help check-ssh start stop restart status logs logs-f logs-app \ - shell-pb pb-admin deploy +.PHONY: help check-ssh start stop restart status logs logs-app logs-f deploy \ + staging-deploy staging-reset staging-seed staging-logs staging-status staging-stop # ---------------------------------------------------------- # Hilfe @@ -40,17 +31,17 @@ help: @echo "" @echo " vereins.haus — verfügbare Befehle:" @echo "" - @echo " make deploy App bauen + zur DS übertragen + Container neu starten" - @echo " make start Alle Container starten" - @echo " make stop Alle Container stoppen" - @echo " make restart Alle Container neu starten" - @echo " make status Container-Status anzeigen" + @echo " make deploy App bauen + zur DS übertragen + Container neu starten" + @echo " make start Container starten" + @echo " make stop Container stoppen" + @echo " make restart Container neu starten" + @echo " make status Container-Status anzeigen" + @echo " make logs App-Logs (100 Zeilen)" + @echo " make logs-f App Live-Log" @echo "" - @echo " make logs PocketBase-Logs (100 Zeilen)" - @echo " make logs-app App-Logs (100 Zeilen)" - @echo " make logs-f PocketBase Live-Log" - @echo " make shell-pb Shell in PocketBase-Container" - @echo " make pb-admin PocketBase Admin-URL anzeigen" + @echo " make staging-deploy Staging deployen" + @echo " make staging-seed Testdaten einfügen" + @echo " make staging-reset Staging-DB löschen (Neustart)" @echo "" # ---------------------------------------------------------- @@ -65,7 +56,7 @@ check-ssh: fi # ---------------------------------------------------------- -# DEPLOY +# DEPLOY (Production) # ---------------------------------------------------------- deploy: check-ssh @echo "→ Sync zu DS..." @@ -74,23 +65,6 @@ deploy: check-ssh @if [ -f .env ]; then \ cat .env | ssh $(DS_HOST) "cat > $(DS_PATH)/.env"; \ fi - @echo "→ PocketBase Hooks synchronisieren..." - @if ls $(HOOKS_SRC)/*.pb.js 2>/dev/null | grep -q .; then \ - for f in $(HOOKS_SRC)/*.pb.js; do \ - cat "$$f" | ssh $(DS_HOST) "cat > $(HOOKS_DST)/$$(basename $$f)"; \ - done; \ - fi - @echo "→ PocketBase Migrations synchronisieren (nur neue)..." - @ssh $(DS_HOST) "mkdir -p $(MIGRATIONS_DST)" - @if ls $(MIGRATIONS_SRC)/*.js 2>/dev/null | grep -q .; then \ - for f in $(MIGRATIONS_SRC)/*.js; do \ - fname=$$(basename "$$f"); \ - if ! ssh $(DS_HOST) "test -f $(MIGRATIONS_DST)/$$fname" 2>/dev/null; then \ - cat "$$f" | ssh $(DS_HOST) "cat > $(MIGRATIONS_DST)/$$fname"; \ - echo " ✓ $$fname"; \ - fi; \ - done; \ - fi @echo "→ Docker rebuild + restart..." @ssh $(DS_HOST) " \ cd $(DS_PATH) && \ @@ -98,7 +72,7 @@ deploy: check-ssh $(DOCKER) compose build app && \ $(DOCKER) compose up -d" @echo " ✓ Deploy fertig." - @ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER_APP) --tail=10" + @ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER_APP) --tail=15" # ---------------------------------------------------------- # Container-Steuerung @@ -124,27 +98,16 @@ status: check-ssh # Logs # ---------------------------------------------------------- logs: check-ssh - @ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER_PB) --tail=100" - -logs-app: check-ssh @ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER_APP) --tail=100" +logs-app: logs + logs-f: check-ssh - @ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER_PB) -f" - -# ---------------------------------------------------------- -# Shell + Admin -# ---------------------------------------------------------- -shell-pb: check-ssh - @ssh -t $(DS_HOST) "$(DOCKER) exec -it $(CONTAINER_PB) sh" - -pb-admin: - @echo " PocketBase Admin: https://api.vereins.haus/_/" + @ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER_APP) -f" # ============================================================== # STAGING # ============================================================== -.PHONY: staging-deploy staging-reset staging-seed staging-logs staging-status staging-stop staging-deploy: check-ssh @echo "→ Sync zu DS (Staging)..." @@ -153,20 +116,6 @@ staging-deploy: check-ssh @if [ -f .env ]; then \ cat .env | ssh $(DS_HOST) "cat > $(STAGING_PATH)/.env"; \ fi - @echo "→ Hooks synchronisieren (Staging, vollständig)..." - @ssh $(DS_HOST) "mkdir -p $(STAGING_HOOKS)" - @if ls $(HOOKS_SRC)/*.pb.js 2>/dev/null | grep -q .; then \ - for f in $(HOOKS_SRC)/*.pb.js; do \ - cat "$$f" | ssh $(DS_HOST) "cat > $(STAGING_HOOKS)/$$(basename $$f)"; \ - done; \ - fi - @echo "→ Migrations synchronisieren (Staging, immer aktuell)..." - @ssh $(DS_HOST) "mkdir -p $(STAGING_MIGRATIONS)" - @if ls $(MIGRATIONS_SRC)/*.js 2>/dev/null | grep -q .; then \ - for f in $(MIGRATIONS_SRC)/*.js; do \ - cat "$$f" | ssh $(DS_HOST) "cat > $(STAGING_MIGRATIONS)/$$(basename $$f)"; \ - done; \ - fi @echo "→ Docker rebuild + restart (Staging)..." @ssh $(DS_HOST) " \ cd $(STAGING_PATH) && \ @@ -174,31 +123,26 @@ staging-deploy: check-ssh $(DOCKER) compose -f docker-compose.staging.yml build app-staging && \ $(DOCKER) compose -f docker-compose.staging.yml up -d" @echo " ✓ Staging bereit." - @echo " App: https://staging.vereins.haus" - @echo " PocketBase: https://api-staging.vereins.haus/_/" + @echo " App: https://staging.vereins.haus" -# Löscht alle PB-Daten auf Staging → Migrations laufen frisch durch +# Löscht die SQLite-DB auf Staging → frischer Start # Danach: make staging-deploy && make staging-seed staging-reset: check-ssh staging-stop - @echo "→ PocketBase-Daten auf Staging löschen..." - @ssh $(DS_HOST) "rm -rf \ - $(STAGING_PATH)/pocketbase/data/storage \ - '$(STAGING_PATH)/pocketbase/data/data.db' \ - '$(STAGING_PATH)/pocketbase/data/data.db-wal' \ - '$(STAGING_PATH)/pocketbase/data/data.db-shm' \ - $(STAGING_PATH)/pocketbase/migrations" - @echo "→ Alle Hooks auf Staging löschen (werden via staging-deploy neu geschrieben)..." - @ssh $(DS_HOST) "rm -f $(STAGING_HOOKS)/*.pb.js" + @echo "→ Staging-Daten löschen..." + @ssh $(DS_HOST) "rm -f \ + $(STAGING_PATH)/data/vereinshaus.db \ + $(STAGING_PATH)/data/vereinshaus.db-wal \ + $(STAGING_PATH)/data/vereinshaus.db-shm && \ + rm -rf $(STAGING_PATH)/data/uploads" @echo " ✓ Reset fertig. Jetzt: make staging-deploy && make staging-seed" staging-seed: @echo "→ Testdaten in Staging einfügen..." - @echo " Voraussetzung: PB_EMAIL + PB_PASSWORD in .env gesetzt (Staging-Superuser)" @if [ -f .env ]; then \ export $$(grep -v '^#' .env | xargs) && \ - PB_URL=https://api-staging.vereins.haus node scripts/seed.js; \ + APP_URL=https://staging.vereins.haus node scripts/seed.js; \ else \ - PB_URL=https://api-staging.vereins.haus node scripts/seed.js; \ + APP_URL=https://staging.vereins.haus node scripts/seed.js; \ fi staging-logs: check-ssh diff --git a/app/Dockerfile b/app/Dockerfile index ed16918..bd6f749 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -1,13 +1,13 @@ FROM node:22-alpine AS builder +RUN apk add --no-cache python3 make g++ WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . -ARG VITE_PB_URL=http://vereinshaus-pocketbase:8090 -ENV VITE_PB_URL=$VITE_PB_URL RUN npm run build FROM node:22-alpine +RUN apk add --no-cache python3 make g++ WORKDIR /app COPY --from=builder /app/build ./build COPY --from=builder /app/package*.json ./ diff --git a/app/package-lock.json b/app/package-lock.json index 89829cd..f27e45c 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -9,7 +9,10 @@ "version": "0.1.0", "dependencies": { "@event-calendar/core": "^5.7.0", + "bcryptjs": "^3.0.3", + "better-sqlite3": "^12.10.0", "ical-generator": "^10.2.0", + "jose": "^6.2.3", "papaparse": "^5.5.3", "pocketbase": "^0.26.9", "rrule": "^2.8.1", @@ -19,6 +22,8 @@ "@sveltejs/adapter-node": "^5.5.4", "@sveltejs/kit": "^2.57.0", "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@types/bcryptjs": "^2.4.6", + "@types/better-sqlite3": "^7.6.13", "@types/papaparse": "^5.5.2", "@types/web-push": "^3.6.4", "svelte": "^5.55.2", @@ -2637,6 +2642,23 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/bcryptjs": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", @@ -2895,6 +2917,26 @@ "node": "18 || 20 || >=22" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.10.31", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz", @@ -2908,6 +2950,49 @@ "node": ">=6.0.0" } }, + "node_modules/bcryptjs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", + "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==", + "license": "BSD-3-Clause", + "bin": { + "bcrypt": "bin/bcrypt" + } + }, + "node_modules/better-sqlite3": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.10.0.tgz", + "integrity": "sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/bn.js": { "version": "4.12.3", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", @@ -2961,6 +3046,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3061,6 +3170,12 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -3221,6 +3336,30 @@ } } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -3271,7 +3410,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -3330,6 +3468,15 @@ "dev": true, "license": "ISC" }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es-abstract": { "version": "1.24.2", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", @@ -3529,6 +3676,15 @@ "url": "https://github.com/bgub/eta?sponsor=1" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3578,6 +3734,12 @@ } } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, "node_modules/filelist": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", @@ -3651,6 +3813,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -3807,6 +3975,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, "node_modules/glob": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", @@ -4030,12 +4204,38 @@ "dev": true, "license": "ISC" }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -4508,6 +4708,15 @@ "node": ">=10" } }, + "node_modules/jose": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", + "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4922,6 +5131,18 @@ "node": ">= 0.4" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -4963,6 +5184,12 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -5008,6 +5235,36 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-releases": { "version": "2.0.44", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", @@ -5070,6 +5327,15 @@ ], "license": "MIT" }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", @@ -5210,6 +5476,33 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/pretty-bytes": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", @@ -5223,6 +5516,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5233,6 +5536,35 @@ "node": ">=6" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -5758,6 +6090,51 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/sirv": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", @@ -5842,6 +6219,15 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -5954,6 +6340,15 @@ "node": ">=10" } }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -6027,6 +6422,34 @@ "@types/estree": "^1.0.6" } }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -6118,6 +6541,18 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-fest": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", @@ -6358,6 +6793,12 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/vite": { "version": "8.0.13", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", @@ -6850,6 +7291,12 @@ "workbox-core": "7.4.1" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/app/package.json b/app/package.json index e84b59f..9f4431d 100644 --- a/app/package.json +++ b/app/package.json @@ -15,6 +15,8 @@ "@sveltejs/adapter-node": "^5.5.4", "@sveltejs/kit": "^2.57.0", "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@types/bcryptjs": "^2.4.6", + "@types/better-sqlite3": "^7.6.13", "@types/papaparse": "^5.5.2", "@types/web-push": "^3.6.4", "svelte": "^5.55.2", @@ -27,7 +29,10 @@ }, "dependencies": { "@event-calendar/core": "^5.7.0", + "bcryptjs": "^3.0.3", + "better-sqlite3": "^12.10.0", "ical-generator": "^10.2.0", + "jose": "^6.2.3", "papaparse": "^5.5.3", "pocketbase": "^0.26.9", "rrule": "^2.8.1", diff --git a/app/src/app.d.ts b/app/src/app.d.ts new file mode 100644 index 0000000..d437a87 --- /dev/null +++ b/app/src/app.d.ts @@ -0,0 +1,15 @@ +declare global { + namespace App { + interface Locals { + user: { + id: string; + verein_id: string; + rolle: string | null; + name: string; + email: string; + } | null; + } + } +} + +export {}; diff --git a/app/src/app.html b/app/src/app.html index 1462822..242c835 100644 --- a/app/src/app.html +++ b/app/src/app.html @@ -9,7 +9,7 @@ - + %sveltekit.head%
diff --git a/app/src/lib/api.ts b/app/src/lib/api.ts new file mode 100644 index 0000000..5db04ec --- /dev/null +++ b/app/src/lib/api.ts @@ -0,0 +1,66 @@ +import { get } from 'svelte/store'; +import { user } from './user'; +import { goto } from '$app/navigation'; + +function token() { return get(user)?.token ?? ''; } + +function headers(extra: Record