diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..485abc7 --- /dev/null +++ b/.env.example @@ -0,0 +1,30 @@ +# Docker compose env + +MONGO_LOCAL_PORT=27017 +BACKEND_LOCAL_PORT=8080 +FRONTEND_LOCAL_PORT=3000 +VITE_BACKEND_URL=http://backend:8080 + +# MongoDB Environment +MONGO_INITDB_DATABASE=getaroom +MONGO_INITDB_ROOT_USERNAME=root +MONGO_INITDB_ROOT_PASSWORD=testroot +MONGO_EXPRESS_USERNAME=admin +MONGO_EXPRESS_PASSWORD=testadmin + +DB_OVERRIDE_URL=mongodb://getaroom:getaroom@mongodb/getaroom?retryWrites=true&w=majority +ME_CONFIG_MONGODB_URL=mongo://root:testroot@mongodb + +# Secret for JWT token, could be any long random string +JWT_SECRET="foobarbaz123foobarbaz123foobarbaz123foobarbaz123" + +# Client ID is found here: (https://console.cloud.google.com/apis/credentials?project=get-a-room-326217), go to "OAuth 2.0 Client IDs" -> "Get A Room!" -> "Client ID" +GOOGLE_CLIENT_ID="" + +# Client secret is found here: (https://console.cloud.google.com/apis/credentials?project=get-a-room-326217), go to "OAuth 2.0 Client IDs" -> "Get A Room!" -> "Client secret" +GOOGLE_CLIENT_SECRET="" + +# Google Customer ID is found here: (https://admin.google.com/ac/accountsettings/profile) +GOOGLE_CUSTOMER_ID="" + +TZ=Etc/UTC \ No newline at end of file diff --git a/.gitignore b/.gitignore index 49905f7..aa76597 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ yarn-error.log* .env *.iml .idea +.vapidkey diff --git a/README.md b/README.md index 14b330c..328ffc3 100644 --- a/README.md +++ b/README.md @@ -58,3 +58,36 @@ After this you probably want to point some domain to this application. This can As a last thing, new OAuth 2.0 Client should be created in Google Cloud -> "APIs and services" -> "CREATE CREDENTIALS" -> "OAuth Client ID". Application type is "Web Application". Authorized JavaScript origins can be left empty. And to the "Authorised redirect URIs" this URL should be added: "https://yourdomainname.com/api/auth/google/callback" And of course remember to replace "yourdomainname" with the new domain name that was reserved for this application. Now you should have a working GitHub actions deployment and a new environment! + +## Running local dev environment + +
+ +### Docker compose + + 1. Copy .env.example files to .env files in + / + /frontend + /backend + 2. Edit root env file and add GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET and GOOGLE_CUSTOMER_ID values + 3. Run docker compose build && docker compose up -d + +
+ +### Npm + +MongoDb needed + + 1. Copy .env.example files to .env files in + /frontend + /backend + 2. Run npm install + 3. Run npm run generate_vapid_keys + 4. Copy VAPID keys from logged output to backend and frontend .env files + 5. Add GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET and GOOGLE_CUSTOMER_ID and database setting to .env-files + 6. Run npm run nodemon in /backend folder + 7. Run npm run start in /frontend folder + +
+ +After frontend startup go to /login page and log in with valid OAuth-user. diff --git a/backend/Dockerfile b/backend/Dockerfile index 8ba5315..aaba425 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,6 +1,6 @@ # Use the official lightweight Node.js 12 image. # https://hub.docker.com/_/node -FROM node:16-slim +FROM node:20 # Create and change to the app directory. WORKDIR /usr/src/app diff --git a/backend/package-lock.json b/backend/package-lock.json index 9658054..6e9d043 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -23,11 +23,11 @@ "express": "^4.19.2", "express-unless": "^2.1.3", "express-validator": "^7.1.0", - "googleapis": "^88.2.0", + "googleapis": "^142.0.0", "helmet": "^7.1.0", "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", - "luxon": "^3.4.4", + "luxon": "^3.5.0", "mongoose": "^8.4.1", "morgan": "^1.10.0", "node-schedule": "^2.1.1", @@ -49,7 +49,7 @@ "web-push": "^3.6.7" }, "engines": { - "node": ">=20.14.0" + "node": ">=20.12.2" } }, "node_modules/@ampproject/remapping": { @@ -2167,17 +2167,6 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2222,6 +2211,8 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "peer": true, "dependencies": { "debug": "4" }, @@ -2233,6 +2224,8 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "optional": true, + "peer": true, "dependencies": { "ms": "2.1.2" }, @@ -2248,7 +2241,9 @@ "node_modules/agent-base/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true, + "peer": true }, "node_modules/ajv": { "version": "6.12.6", @@ -2358,14 +2353,6 @@ "node": ">=8" } }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "engines": { - "node": ">=8" - } - }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -3575,14 +3562,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3766,11 +3745,6 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" - }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -3919,30 +3893,74 @@ } }, "node_modules/gaxios": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.2.tgz", - "integrity": "sha512-T+ap6GM6UZ0c4E6yb1y/hy2UB6hTrqhglp3XfmU9qbLCGRYhLVV5aRPpC4EmoG8N8zOnkYCgoBz+ScvGAARY6Q==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", "dependencies": { - "abort-controller": "^3.0.0", "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", + "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", - "node-fetch": "^2.6.1" + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" }, "engines": { - "node": ">=10" + "node": ">=14" } }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", "dependencies": { - "gaxios": "^4.0.0", + "gaxios": "^6.0.0", "json-bigint": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/gensync": { @@ -4064,64 +4082,47 @@ } }, "node_modules/google-auth-library": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.10.0.tgz", - "integrity": "sha512-ICsqaU+lxMHVlDUzMrfVIEqnARw2AwBiZ/2KnNM6BcTf9Nott+Af87DTIzmlnW865p3REUP2MVL0xkPC3a61aQ==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.14.0.tgz", + "integrity": "sha512-Y/eq+RWVs55Io/anIsm24sDS8X79Tq948zVLGaa7+KlJYYqaGwp1YI37w48nzrNi12RgnzMrQD4NzdmCowT90g==", "dependencies": { - "arrify": "^2.0.0", "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/google-p12-pem": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", - "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", - "dependencies": { - "node-forge": "^1.3.1" - }, - "bin": { - "gp12-pem": "build/src/bin/gp12-pem.js" + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/googleapis": { - "version": "88.2.0", - "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-88.2.0.tgz", - "integrity": "sha512-z3iDvGVqaJ+4TZ7YulK530q5vkY0BifvAWqcu2JiUSgpnIHzsA89k005+McoaYB+lAgv7lPY2Y4OPMT6iloWRA==", + "version": "142.0.0", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-142.0.0.tgz", + "integrity": "sha512-LsU1ynez4/KNPwnFMSDI93pBEsETNdQPCrT3kz2qgiNg5H2pW4dKW+1VmENMkZ4u9lMxA89nnXD3nqWBJ0rruQ==", "dependencies": { - "google-auth-library": "^7.0.2", - "googleapis-common": "^5.0.2" + "google-auth-library": "^9.0.0", + "googleapis-common": "^7.0.0" }, "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, "node_modules/googleapis-common": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-5.0.5.tgz", - "integrity": "sha512-o2dgoW4x4fLIAN+IVAOccz3mEH8Lj1LP9c9BSSvkNJEn+U7UZh0WSr4fdH08x5VH7+sstIpd1lOYFZD0g7j4pw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-7.2.0.tgz", + "integrity": "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==", "dependencies": { "extend": "^3.0.2", - "gaxios": "^4.0.0", - "google-auth-library": "^7.0.2", + "gaxios": "^6.0.3", + "google-auth-library": "^9.7.0", "qs": "^6.7.0", "url-template": "^2.0.8", - "uuid": "^8.0.0" + "uuid": "^9.0.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=14.0.0" } }, "node_modules/gopd": { @@ -4148,16 +4149,15 @@ "dev": true }, "node_modules/gtoken": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.1.tgz", - "integrity": "sha512-yqOREjzLHcbzz1UrQoxhBtpk8KjrVhuqPE7od1K2uhyxG2BHjKZetlbLw/SPZak/QqTIQW+addS+EcjqQsZbwQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", "dependencies": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.0.3", + "gaxios": "^6.0.0", "jws": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, "node_modules/has": { @@ -4267,6 +4267,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "optional": true, + "peer": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -4279,6 +4281,8 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "optional": true, + "peer": true, "dependencies": { "ms": "2.1.2" }, @@ -4294,7 +4298,9 @@ "node_modules/https-proxy-agent/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true, + "peer": true }, "node_modules/human-signals": { "version": "2.1.0", @@ -6034,21 +6040,10 @@ "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==" }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/luxon": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", - "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", "engines": { "node": ">=12" } @@ -6433,14 +6428,6 @@ } } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7667,7 +7654,7 @@ "node_modules/url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" }, "node_modules/utils-merge": { "version": "1.0.1", @@ -7678,9 +7665,13 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -7872,11 +7863,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -9574,14 +9560,6 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -9612,6 +9590,8 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "peer": true, "requires": { "debug": "4" }, @@ -9620,6 +9600,8 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "optional": true, + "peer": true, "requires": { "ms": "2.1.2" } @@ -9627,7 +9609,9 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true, + "peer": true } } }, @@ -9710,11 +9694,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" - }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -10557,11 +10536,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -10706,11 +10680,6 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" - }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -10827,23 +10796,55 @@ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "gaxios": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.2.tgz", - "integrity": "sha512-T+ap6GM6UZ0c4E6yb1y/hy2UB6hTrqhglp3XfmU9qbLCGRYhLVV5aRPpC4EmoG8N8zOnkYCgoBz+ScvGAARY6Q==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", "requires": { - "abort-controller": "^3.0.0", "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", + "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", - "node-fetch": "^2.6.1" + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "dependencies": { + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "requires": { + "debug": "^4.3.4" + } + }, + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } } }, "gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", "requires": { - "gaxios": "^4.0.0", + "gaxios": "^6.0.0", "json-bigint": "^1.0.0" } }, @@ -10927,49 +10928,38 @@ } }, "google-auth-library": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.10.0.tgz", - "integrity": "sha512-ICsqaU+lxMHVlDUzMrfVIEqnARw2AwBiZ/2KnNM6BcTf9Nott+Af87DTIzmlnW865p3REUP2MVL0xkPC3a61aQ==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.14.0.tgz", + "integrity": "sha512-Y/eq+RWVs55Io/anIsm24sDS8X79Tq948zVLGaa7+KlJYYqaGwp1YI37w48nzrNi12RgnzMrQD4NzdmCowT90g==", "requires": { - "arrify": "^2.0.0", "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - } - }, - "google-p12-pem": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", - "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", - "requires": { - "node-forge": "^1.3.1" + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" } }, "googleapis": { - "version": "88.2.0", - "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-88.2.0.tgz", - "integrity": "sha512-z3iDvGVqaJ+4TZ7YulK530q5vkY0BifvAWqcu2JiUSgpnIHzsA89k005+McoaYB+lAgv7lPY2Y4OPMT6iloWRA==", + "version": "142.0.0", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-142.0.0.tgz", + "integrity": "sha512-LsU1ynez4/KNPwnFMSDI93pBEsETNdQPCrT3kz2qgiNg5H2pW4dKW+1VmENMkZ4u9lMxA89nnXD3nqWBJ0rruQ==", "requires": { - "google-auth-library": "^7.0.2", - "googleapis-common": "^5.0.2" + "google-auth-library": "^9.0.0", + "googleapis-common": "^7.0.0" } }, "googleapis-common": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-5.0.5.tgz", - "integrity": "sha512-o2dgoW4x4fLIAN+IVAOccz3mEH8Lj1LP9c9BSSvkNJEn+U7UZh0WSr4fdH08x5VH7+sstIpd1lOYFZD0g7j4pw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-7.2.0.tgz", + "integrity": "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==", "requires": { "extend": "^3.0.2", - "gaxios": "^4.0.0", - "google-auth-library": "^7.0.2", + "gaxios": "^6.0.3", + "google-auth-library": "^9.7.0", "qs": "^6.7.0", "url-template": "^2.0.8", - "uuid": "^8.0.0" + "uuid": "^9.0.0" } }, "gopd": { @@ -10993,12 +10983,11 @@ "dev": true }, "gtoken": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.1.tgz", - "integrity": "sha512-yqOREjzLHcbzz1UrQoxhBtpk8KjrVhuqPE7od1K2uhyxG2BHjKZetlbLw/SPZak/QqTIQW+addS+EcjqQsZbwQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", "requires": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.0.3", + "gaxios": "^6.0.0", "jws": "^4.0.0" } }, @@ -11076,6 +11065,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "optional": true, + "peer": true, "requires": { "agent-base": "6", "debug": "4" @@ -11085,6 +11076,8 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "optional": true, + "peer": true, "requires": { "ms": "2.1.2" } @@ -11092,7 +11085,9 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true, + "peer": true } } }, @@ -12457,18 +12452,10 @@ "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==" }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, "luxon": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", - "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==" }, "make-dir": { "version": "4.0.0", @@ -12732,11 +12719,6 @@ "whatwg-url": "^5.0.0" } }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" - }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -13574,7 +13556,7 @@ "url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" }, "utils-merge": { "version": "1.0.1", @@ -13582,9 +13564,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "v8-compile-cache-lib": { "version": "3.0.1", @@ -13730,11 +13712,6 @@ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/backend/package.json b/backend/package.json index 4b8eaa5..59a5c8e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -15,6 +15,7 @@ "build": "tsc --project tsconfig.production.json", "start": "ts-node src/app.ts", "nodemon": "nodemon -e js,ts,json src/app.ts", + "generate_vapid_keys": "node ../scripts/generateVAPIDKeys.js", "start-production": "node build/app.js" }, "author": "", @@ -34,11 +35,11 @@ "express": "^4.19.2", "express-unless": "^2.1.3", "express-validator": "^7.1.0", - "googleapis": "^88.2.0", + "googleapis": "^142.0.0", "helmet": "^7.1.0", "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", - "luxon": "^3.4.4", + "luxon": "^3.5.0", "mongoose": "^8.4.1", "morgan": "^1.10.0", "node-schedule": "^2.1.1", diff --git a/backend/src/authMiddleware.ts b/backend/src/authMiddleware.ts index afd3a71..c03ad18 100644 --- a/backend/src/authMiddleware.ts +++ b/backend/src/authMiddleware.ts @@ -51,8 +51,21 @@ export const parseToken = (): ExpressMiddlewareWithUnless => { } const payload = readToken(TOKEN); - if (!payload.refreshToken) { + console.warn( + 'oAuth refresh token not found. Revoking access token', + payload + ); + + getOAuthClient() + .revokeToken(payload.accessToken) + .then(() => { + console.warn('Access token revoked', payload); + }) + .catch((reason) => { + console.error('Error revoking access token', reason); + }); + return responses.invalidToken(req, res); } @@ -94,7 +107,6 @@ export const validateAccessToken = (): ExpressMiddlewareWithUnless => { }); const newToken = (await client.getAccessToken()).token; - if (!newToken) { return responses.invalidToken(req, res); } diff --git a/dev.Dockerfile b/dev.Dockerfile new file mode 100644 index 0000000..ebe14e3 --- /dev/null +++ b/dev.Dockerfile @@ -0,0 +1,20 @@ +FROM node:20 + +ARG DIR +ARG TZ +WORKDIR /usr/src/app + +COPY . /usr/src/app + +WORKDIR /usr/src/app/${DIR} + +RUN npm install + +RUN npm run build + +ENV BACKEND_URL ${BACKEND_URL} + +ENV TZ=${TZ} +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +VOLUME /usr/src/app \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..4f892a5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,107 @@ +services: + mongodb: + image: mongo:7 + container_name: getaroom-mongodb + hostname: mongodb + volumes: + - ./db/mongodb-single/mongodb/initdb.d/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro + env_file: + - .env + environment: + MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME} + MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD} + MONGO_INITDB_DATABASE: ${MONGO_INITDB_DATABASE} + ports: + - '${MONGO_LOCAL_PORT}:27017' + networks: + - getaroom_network + healthcheck: + test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet + interval: 10s + timeout: 10s + retries: 2 + start_period: 5s + + mongo-express: + image: mongo-express:latest + container_name: getaroom-mongo-express + restart: always + environment: + - ME_CONFIG_MONGODB_SERVER=mongodb + - ME_CONFIG_MONGODB_URL=${ME_CONFIG_MONGODB_URL} + - ME_CONFIG_MONGODB_ADMINUSERNAME=${MONGO_INITDB_ROOT_USERNAME} + - ME_CONFIG_MONGODB_ADMINPASSWORD=${MONGO_INITDB_ROOT_PASSWORD} + - ME_CONFIG_BASICAUTH_PASSWORD=${MONGO_EXPRESS_PASSWORD} + - ME_CONFIG_MONGODB_PORT=27017 + - ME_CONFIG_BASICAUTH_USERNAME=${MONGO_EXPRESS_USERNAME} + ports: + - 8081:8081 + networks: + - getaroom_network + depends_on: + mongodb: + condition: service_healthy + + backend: + env_file: + - .env + build: + context: . + dockerfile: ./dev.Dockerfile + args: + - DIR=backend + - TZ=${TZ} + container_name: getaroom-backend + hostname: backend + volumes: + - ./:/usr/src/app/ + ports: + - '${BACKEND_LOCAL_PORT}:8080' + networks: + - getaroom_network + healthcheck: + test: curl --fail http://localhost:8080/api || exit 1 + interval: 20s + retries: 5 + start_period: 5s + timeout: 10s + depends_on: + mongodb: + condition: service_healthy + command: | + bash -c " + npm --prefix /usr/src/app/backend run generate_vapid_keys && + export VAPID_PUBLIC_KEY="$(sed -n '1p' ../.vapidkey)" && + export VAPID_PRIVATE_KEY="$(sed -n '2p' ../.vapidkey)" && + npm run nodemon + " + frontend: + env_file: + - .env + build: + context: . + dockerfile: ./dev.Dockerfile + args: + - DIR=frontend + - TZ=${TZ} + container_name: getaroom-frontend + depends_on: + backend: + condition: service_healthy + hostname: frontend + volumes: + - ./:/usr/src/app/ + ports: + - '${FRONTEND_LOCAL_PORT}:3000' + expose: + - 3000 + networks: + - getaroom_network + command: | + bash -c "export VITE_REACT_APP_SERVER_KEY="$(sed -n '1p' ../.vapidkey)" + npm run start:docker --host" + +networks: + getaroom_network: + driver: bridge + name: getaroom_network diff --git a/frontend/index.html b/frontend/index.html index 85b25c9..1cb8a7b 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,7 +3,7 @@ - + import { Box, Stack, Typography } from '@mui/material'; import GoogleLogin from './GoogleLogin'; -import { DuckLogo } from '../images/svgImages'; +import { styled } from '@mui/material/styles'; +import { COLORS } from '../../theme_2024'; + +const LoginWrapper = styled('div')(({ theme }) => ({ + display: 'flex', + width: '100%', + minWidth: '375px', + height: 'calc(431px+616px)', + minHeight: 'calc(431px+616px)', + flexShrink: 0, + background: COLORS.BACKGROUND_PRIMARY, + justifyContent: 'center' +})); + +const LoginHeader = styled(Stack)(({ theme }) => ({ + position: 'absolute', + top: 0, + left: 0, + backgroundImage: 'url(login_background.jpeg)', + alignItems: 'center', + justifyContent: 'center', + width: '100%', + minWidth: '375px', + height: 'calc(431px / (431px+616px) * 100%)', + minHeight: '431px', + flexShrink: 0, + marginTop: 0, + background: + 'linear-gradient(179deg, rgba(251, 251, 246, 0.00) 69.25%, rgba(251, 251, 246, 0.20) 99.55%), linear-gradient(0deg, rgba(0, 0, 0, 0.60) 0%, rgba(0, 0, 0, 0.60) 100%), url(login_background.jpeg) lightgray 50% / cover no-repeat' +})); + +const LoginTitle = styled(Typography)(({ theme }) => ({ + lineHeight: 'normal', + textTransform: 'uppercase', + color: COLORS.BACKGROUND_WHITE, + justifyContent: 'center', + fontSize: '2em', + marginTop: '4%', + marginBottom: '20%' +})); + +const LoginContent = styled(Box)(({ theme }) => ({ + marginTop: '275px', + width: '105%', + display: 'inline-flex', + height: '616px', + padding: '70px 24px', + flexDirection: 'column', + alignItems: 'center', + gap: '54px', + flexShrink: 0, + zIndex: 100, + + borderRadius: '160px', + background: 'var(--Colors-General-Layout-Colors-Background-Color, #FBFBF6)' +})); + +const Logo = () => ( + +); const LoginView = () => { return ( - - + + + + Get a Room! + + + - - Get a Room! - - + + Meeting rooms on the fly - - - - - - - - + + + ); }; diff --git a/frontend/src/theme_2024.ts b/frontend/src/theme_2024.ts index 8afbeba..3f2b899 100644 --- a/frontend/src/theme_2024.ts +++ b/frontend/src/theme_2024.ts @@ -27,8 +27,8 @@ export const COLORS = { ACCENT_RED: '#E83520', TEXT_PRIMARY: '#1D1D1D', TEXT_DIMGREY: '#A4A4A4', - BACKGROUND_PRIMARY: '#FFF', - BACKGROUND_DIM: '#FBFBF6', + BACKGROUND_WHITE: '#FFF', + BACKGROUND_PRIMARY: '#FBFBF6', ALTERNATE: '#FBFBF6' }; diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index aecc3d9..2f3e383 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -41,6 +41,7 @@ export default defineConfig(({ mode }) => { optimizeDeps: { include: ['@emotion/styled', '@mui/styled-engine'] }, + useCredentials: true, server: { // this ensures that the browser opens upon server start open: true, @@ -49,9 +50,9 @@ export default defineConfig(({ mode }) => { proxy: { // with options: http://localhost:5173/api/bar-> http://jsonplaceholder.typicode.com/bar '/api': { - target: 'http://localhost:8080', + target: env.VITE_BACKEND_URL || 'http://localhost:8080', changeOrigin: false, - secure: true + secure: false // rewrite: (path) => path.replace(/^\/api/, '') } } diff --git a/scripts/generateVAPIDKeys.js b/scripts/generateVAPIDKeys.js new file mode 100644 index 0000000..b81180d --- /dev/null +++ b/scripts/generateVAPIDKeys.js @@ -0,0 +1,15 @@ +import webpush from 'web-push'; + +import fs from 'node:fs'; + +try { + fs.statSync('../.vapidkey'); +} catch (err) { + const vapidKey = webpush.generateVAPIDKeys(); + console.log(`Created publickey: ${vapidKey.publicKey}`); + console.log(`Created privatekey: ${vapidKey.privateKey}`); + fs.writeFileSync( + '../.vapidkey', + `${vapidKey.publicKey}\n${vapidKey.privateKey}\n` + ); +}