diff --git a/.env.example b/.env.example index facfae9..cea10bd 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ DATABASE_URI=sqlite://./database.db +ADMIN_USER=admin +ADMIN_PASSWORD=admin PUBLIC_START_DATE=2023-12-26T00:00:00+0200 PUBLIC_BASE_PATH= diff --git a/README.md b/README.md index 42c8e8d..0207f9a 100644 --- a/README.md +++ b/README.md @@ -34,5 +34,7 @@ Configurations can be done with env variables | `HOST` | Host the server should listen on | | `PORT` | Port the server should listen on | | `DATABASE_URI` | URI to the database as a connection string. Supported databases are [sqlite](https://www.sqlite.org/index.html) and [mariadb](https://mariadb.org/) | +| `ADMIN_USER` | Name for the root admin user. The admin user won't be available if `ADMIN_USER` or `ADMIN_PASSWORD` is set | +| `ADMIN_PASSWORD` | Password for the root admin user defined via `ADMIN_USER`. The admin user won't be available if `ADMIN_USER` or `ADMIN_PASSWORD` is set | | `PUBLIC_BASE_PATH` | If running the website on a sub-path, set this variable to the path so that assets etc. can find the correct location | | `PUBLIC_START_DATE` | The start date when the event starts | diff --git a/package-lock.json b/package-lock.json index 5d8cf8f..f8f8388 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,18 +8,23 @@ "name": "website", "version": "0.0.1", "dependencies": { + "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "mariadb": "^3.2.0", "sequelize": "^6.32.1", + "sequelize-typescript": "^2.1.5", "sqlite3": "^5.1.6" }, "devDependencies": { "@sveltejs/adapter-node": "^1.3.1", "@sveltejs/kit": "^1.20.4", + "@types/bcrypt": "^5.0.0", + "@types/node": "^20.5.6", + "@types/validator": "^13.11.1", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "autoprefixer": "^10.4.14", - "daisyui": "^3.5.0", + "daisyui": "^3.6.3", "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-svelte": "^2.30.0", @@ -946,6 +951,15 @@ "node": ">= 6" } }, + "node_modules/@types/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/chai": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", @@ -998,9 +1012,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.4.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", - "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==" + "version": "20.5.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.6.tgz", + "integrity": "sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==" }, "node_modules/@types/pug": { "version": "2.0.6", @@ -1540,6 +1554,24 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bcrypt/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1951,9 +1983,9 @@ } }, "node_modules/daisyui": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-3.5.0.tgz", - "integrity": "sha512-wSaeXwaYdMv4yURv9wj7kKQQN9Jyumfh/skIpZfCNkCb2jLf/so+iNKSM8l4rDN0TRvB5OccMlAvsf2UAtk2gg==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-3.6.3.tgz", + "integrity": "sha512-VNWogAjx37H8kNYd2E/+r1OXc6dOvJTKlKltqIKAlNMFVfx2BIKPcmnVxaHQLfj2vhv1mYDBjgWj+1enQ+4yZA==", "dev": true, "dependencies": { "colord": "^2.9", @@ -4190,6 +4222,12 @@ "node": ">=8.10.0" } }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "peer": true + }, "node_modules/resolve": { "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", @@ -4436,6 +4474,42 @@ "node": ">= 10.0.0" } }, + "node_modules/sequelize-typescript": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-2.1.5.tgz", + "integrity": "sha512-x1CNODct8gJyfZPwEZBU5uVGNwgJI2Fda913ZxD5ZtCSRyTDPBTS/0uXciF+MlCpyqjpmoCAPtudQWzw579bzA==", + "dependencies": { + "glob": "7.2.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "@types/validator": "*", + "reflect-metadata": "*", + "sequelize": ">=6.20.1" + } + }, + "node_modules/sequelize-typescript/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", diff --git a/package.json b/package.json index 2c14343..e795aad 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,13 @@ "devDependencies": { "@sveltejs/adapter-node": "^1.3.1", "@sveltejs/kit": "^1.20.4", + "@types/bcrypt": "^5.0.0", + "@types/node": "^20.5.6", + "@types/validator": "^13.11.1", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "autoprefixer": "^10.4.14", - "daisyui": "^3.5.0", + "daisyui": "^3.6.3", "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-svelte": "^2.30.0", @@ -38,9 +41,11 @@ }, "type": "module", "dependencies": { + "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "mariadb": "^3.2.0", "sequelize": "^6.32.1", + "sequelize-typescript": "^2.1.5", "sqlite3": "^5.1.6" } } diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 125fd7f..6e4794d 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,4 +1,25 @@ import { sequelize } from '$lib/server/database'; +import type { Handle } from '@sveltejs/kit'; +import { env } from '$env/dynamic/public'; +import { hasSession } from '$lib/server/session'; // make sure that the database and tables exist await sequelize.sync(); + +export const handle: Handle = async ({ event, resolve }) => { + if ( + event.url.pathname.startsWith(`${env.PUBLIC_BASE_PATH}/admin`) && + event.url.pathname != `${env.PUBLIC_BASE_PATH}/admin/login` + ) { + if (!hasSession(event.cookies.get('session') || '')) { + return new Response(null, { + status: 302, + headers: { + location: `${env.PUBLIC_BASE_PATH}/admin/login` + } + }); + } + } + + return resolve(event); +}; diff --git a/src/lib/components/Input/Input.svelte b/src/lib/components/Input/Input.svelte index 7fb1573..7e4ee9e 100644 --- a/src/lib/components/Input/Input.svelte +++ b/src/lib/components/Input/Input.svelte @@ -31,10 +31,11 @@ {/if} -