From b96b44d10bb484aaf9a855483fa74ebbfc465fb2 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Mon, 15 Jan 2024 21:23:13 -0800 Subject: [PATCH 01/38] Created User Schema --- backend/src/app.ts | 2 ++ backend/src/models/User.ts | 22 ++++++++++++++++++++++ backend/src/routes/userRoute.ts | 0 3 files changed, 24 insertions(+) create mode 100644 backend/src/models/User.ts create mode 100644 backend/src/routes/userRoute.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index 4d9588a4..6ee359ff 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -2,6 +2,8 @@ import { json } from "body-parser"; import express from "express"; import mongoose from "mongoose"; +// import userRoute from './routes/userRoute' + import { mongoURI, port } from "./config"; /** diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts new file mode 100644 index 00000000..747fb4ea --- /dev/null +++ b/backend/src/models/User.ts @@ -0,0 +1,22 @@ +import mongoose, { Document } from "mongoose"; + +// email and password stored in Firebase +// name, gender, account type (Admin/Team), and approval status stored in MongoDB + +export type UserDocument = { + name: string; + gender: string; + accountType: "admin" | "team"; + approvalStatus: string; // Should this be restricted to certain values? + firebaseUid: string; +} & Document; + +const userSchema = new mongoose.Schema({ + name: { type: String, required: true }, + gender: { type: String, required: true }, + accountType: { type: String, enum: ["admin", "team"], required: true }, + approvalStatus: { type: String, required: true }, + firebaseUid: { type: String, required: true }, +}); + +export default mongoose.model("User", userSchema); diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts new file mode 100644 index 00000000..e69de29b From bd3669d4b0a60bc6863d38a773aafa946a1ea523 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Tue, 16 Jan 2024 17:31:34 -0800 Subject: [PATCH 02/38] Initial Route --- backend/package-lock.json | 1559 ++++++++++++++++++++++++++++++- backend/package.json | 1 + backend/src/app.ts | 7 +- backend/src/models/User.ts | 6 +- backend/src/routes/userRoute.ts | 38 + 5 files changed, 1571 insertions(+), 40 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index a61c0f33..b4fd8036 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -12,6 +12,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "firebase-admin": "^12.0.0", "mongodb": "^6.3.0", "mongoose": "^8.0.3" }, @@ -141,6 +142,219 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fastify/busboy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", + "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", + "dependencies": { + "text-decoding": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz", + "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg==" + }, + "node_modules/@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", + "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" + }, + "node_modules/@firebase/component": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", + "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==", + "dependencies": { + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.2.tgz", + "integrity": "sha512-8X6NBJgUQzDz0xQVaCISoOLINKat594N2eBbMR3Mu/MH/ei4WM+aAMlsNzngF22eljXu1SILP5G3evkyvsG3Ng==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.0", + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.2.tgz", + "integrity": "sha512-09ryJnXDvuycsxn8aXBzLhBTuCos3HEnCOBWY6hosxfYlNCGnLvG8YMlbSAt5eNhf7/00B095AEfDsdrrLjxqA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/database": "1.0.2", + "@firebase/database-types": "1.0.0", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.0.tgz", + "integrity": "sha512-SjnXStoE0Q56HcFgNQ+9SsmJc0c8TqGARdI/T44KXy+Ets3r6x/ivhQozT66bMnCEjJRywYoxNurRTMlZF8VNg==", + "dependencies": { + "@firebase/app-types": "0.9.0", + "@firebase/util": "1.9.3" + } + }, + "node_modules/@firebase/logger": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@google-cloud/firestore": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.1.0.tgz", + "integrity": "sha512-kkTC0Sb9r2lONuFF8Tr2wFfBfk0DT1/EKcTKOhsuoXUVClv3jCqGYVPtHgQsHFjdOsubS+tx9G5D5WG+obB2DA==", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^4.0.4", + "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.0.tgz", + "integrity": "sha512-87aeg6QQcEPxGCOthnpUjvw4xAZ57G7pL8FS0C4e/81fr3FjkpUpibf1s2v5XGyGhUVGF4Jfg7yEcxqn2iUw1w==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.7.0.tgz", + "integrity": "sha512-EMCEY+6JiIkx7Dt8NXVGGjy1vRdSGdHkoqZoqjJw7cEBkT7ZkX0c7puedfn1MamnzW5SX4xoa2jVq5u7OWBmkQ==", + "optional": true, + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "fast-xml-parser": "^4.3.0", + "gaxios": "^6.0.2", + "google-auth-library": "^9.0.0", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@google-cloud/storage/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==", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.9.13", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.13.tgz", + "integrity": "sha512-OEZZu9v9AA+7/tghMDE8o5DAMD5THVnwSqDWuh7PPYO5287rTyqy0xEHT6/e4pbqSrhyLPdQFsam4TwFQVVIIw==", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", + "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "optional": true, + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -265,6 +479,79 @@ "node": ">= 8" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "optional": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -293,17 +580,21 @@ "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" } }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "optional": true + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -321,7 +612,6 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -333,7 +623,6 @@ "version": "4.17.41", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -344,8 +633,7 @@ "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -359,11 +647,24 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "optional": true + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/node": { "version": "20.10.5", @@ -376,14 +677,24 @@ "node_modules/@types/qs": { "version": "6.9.11", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", - "dev": true + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/request": { + "version": "2.48.12", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", + "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", + "optional": true, + "dependencies": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + } }, "node_modules/@types/semver": { "version": "7.5.6", @@ -395,7 +706,6 @@ "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -405,7 +715,6 @@ "version": "1.15.5", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -424,6 +733,12 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "optional": true + }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -794,6 +1109,18 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "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==", + "optional": true, + "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", @@ -836,6 +1163,41 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "optional": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "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==", + "optional": true + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -856,7 +1218,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -865,7 +1227,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "devOptional": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -1023,6 +1385,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "optional": true, + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "optional": true + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -1041,6 +1427,35 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "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" + } + ], + "optional": true + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "optional": true, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1103,6 +1518,11 @@ "node": ">=16.20.1" } }, + "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", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -1182,11 +1602,25 @@ "fsevents": "~2.3.2" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "devOptional": true, "dependencies": { "color-name": "~1.1.4" }, @@ -1198,7 +1632,31 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "devOptional": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "optional": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -1314,6 +1772,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "optional": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1375,6 +1842,18 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "optional": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, "node_modules/dynamic-dedupe": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", @@ -1384,11 +1863,25 @@ "xtend": "^4.0.0" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -1397,6 +1890,21 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "optional": true + }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -1490,6 +1998,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1820,6 +2337,15 @@ "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==", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -1861,11 +2387,17 @@ "node": ">= 0.10.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "devOptional": true }, "node_modules/fast-glob": { "version": "3.3.2", @@ -1895,6 +2427,28 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-xml-parser": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.3.tgz", + "integrity": "sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", @@ -1904,6 +2458,17 @@ "reusify": "^1.0.4" } }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -1961,6 +2526,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/firebase-admin": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.0.0.tgz", + "integrity": "sha512-wBrrSSsKV++/+O8E7O/C7/wL0nbG/x4Xv4yatz/+sohaZ+LsnWtYUcrd3gZutO86hLpDex7xgyrkKbgulmtVyQ==", + "dependencies": { + "@fastify/busboy": "^1.2.1", + "@firebase/database-compat": "^1.0.2", + "@firebase/database-types": "^1.0.0", + "@types/node": "^20.10.3", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^3.0.1", + "node-forge": "^1.3.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^7.1.0", + "@google-cloud/storage": "^7.7.0" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -2005,6 +2592,20 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "optional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2067,6 +2668,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "optional": true + }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -2076,6 +2683,112 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gaxios": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.1.1.tgz", + "integrity": "sha512-bw8smrX+XlAoo9o1JAksBwX+hi/RG15J+NTSxmNPIclKC3ZVK6C2afwY8OSdRvOK0+ZLecUJYtj2MmjOt3Dm0w==", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gcp-metadata": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "optional": true, + "peer": true, + "dependencies": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gcp-metadata/node_modules/agent-base": { + "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" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/gcp-metadata/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/gcp-metadata/node_modules/gaxios": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "optional": true, + "peer": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gcp-metadata/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "peer": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gcp-metadata/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==", + "optional": true, + "peer": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "optional": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", @@ -2188,6 +2901,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/google-auth-library": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.4.2.tgz", + "integrity": "sha512-rTLO4gjhqqo3WvYKL5IdtlCvRqeQ4hxUx/p4lObobY2xotFW3bCQC+Qf1N51CYOfiqfMecdMwW9RIo7dFWYjqw==", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-auth-library/node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "optional": true, + "dependencies": { + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.1.0.tgz", + "integrity": "sha512-VP5MYsIXEoXmdeHZl1Qsjv89PvE+LT8fw/2jxpFQtFed22YYAHgiTUuMfj2RWlGJUmRaYEMxBRBDWj+q/hOGQg==", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "~1.9.6", + "@grpc/proto-loader": "^0.7.0", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^9.0.0", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^2.0.0", + "protobufjs": "7.2.5", + "retry-request": "^7.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -2205,6 +2970,19 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/gtoken": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.0.1.tgz", + "integrity": "sha512-KcFVtoP1CVFtQu0aSk3AyAt2og66PFhZAlkUOuWKwzMLoulHXG5W5wE5xAnHb+yl3/wEFoqGW7/cDGMU8igDZQ==", + "optional": true, + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2297,6 +3075,96 @@ "node": ">= 0.8" } }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "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, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-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==", + "optional": true + }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "optional": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "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==", + "optional": true + }, "node_modules/husky": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", @@ -2496,6 +3364,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2581,6 +3458,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -2650,6 +3539,14 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jose": { + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", + "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2662,6 +3559,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2680,16 +3586,133 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwks-rsa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz", + "integrity": "sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==", + "dependencies": { + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", + "debug": "^4.3.4", + "jose": "^4.14.6", + "limiter": "^1.1.5", + "lru-memoizer": "^2.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jwks-rsa/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/jwks-rsa/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/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" } }, "node_modules/kareem": { @@ -2722,6 +3745,11 @@ "node": ">= 0.8.0" } }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2737,17 +3765,68 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "optional": true + }, "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==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -2755,6 +3834,29 @@ "node": ">=10" } }, + "node_modules/lru-memoizer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz", + "integrity": "sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "~4.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", + "dependencies": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -3097,6 +4199,56 @@ "node": ">= 0.6" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "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/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3114,6 +4266,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -3210,7 +4371,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "devOptional": true, "dependencies": { "wrappy": "1" } @@ -3236,7 +4397,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, + "devOptional": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -3365,6 +4526,42 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/proto3-json-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.0.tgz", + "integrity": "sha512-FB/YaNrpiPkyQNSNPilpn8qn0KdEfkgmJ9JP93PQyF/U4bAiXY5BiUdDhiDO4S48uSQ6AesklgVlrKiqZPzegw==", + "optional": true, + "dependencies": { + "protobufjs": "^7.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3377,6 +4574,11 @@ "node": ">= 0.10" } }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3441,6 +4643,20 @@ "node": ">= 0.8" } }, + "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==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3470,6 +4686,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3496,6 +4721,53 @@ "node": ">=4" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.1.tgz", + "integrity": "sha512-ZI6vJp9rfB71mrZpw+n9p/B6HCsd7QJlSEQftZ+xfJzr3cQ9EPGKw1FF0BnViJ0fYREX6FhymBD2CARpmsFciQ==", + "optional": true, + "dependencies": { + "@types/request": "^2.48.8", + "debug": "^4.1.1", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/retry-request/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/retry-request/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==", + "optional": true + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3764,6 +5036,44 @@ "node": ">= 0.8" } }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.2.tgz", + "integrity": "sha512-rV4Bovi9xx0BFzOb/X0B2GqoIjvqPCttZdu0Wgtx2Dxkj7ETyWl9gmqJ4EutWRLvtZWm8dxE+InQZX1IryZn/w==", + "optional": true + }, + "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==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", @@ -3813,7 +5123,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "devOptional": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3839,6 +5149,18 @@ "node": ">=0.10.0" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "optional": true + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3863,6 +5185,75 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "optional": true, + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/teeny-request/node_modules/agent-base": { + "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, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/teeny-request/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/teeny-request/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==", + "optional": true + }, + "node_modules/text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4022,6 +5413,11 @@ "strip-bom": "^3.0.0" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4173,6 +5569,12 @@ "punycode": "^2.1.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==", + "optional": true + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -4181,6 +5583,18 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "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" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -4203,6 +5617,27 @@ "node": ">=12" } }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/whatwg-url": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", @@ -4265,11 +5700,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=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==", - "dev": true + "devOptional": true }, "node_modules/xtend": { "version": "4.0.2", @@ -4280,11 +5732,46 @@ "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "optional": true, + "engines": { + "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==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "optional": true, + "engines": { + "node": ">=12" + } }, "node_modules/yn": { "version": "3.1.1", @@ -4299,7 +5786,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=10" }, diff --git a/backend/package.json b/backend/package.json index b729c588..eb8663e1 100644 --- a/backend/package.json +++ b/backend/package.json @@ -18,6 +18,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "firebase-admin": "^12.0.0", "mongodb": "^6.3.0", "mongoose": "^8.0.3" }, diff --git a/backend/src/app.ts b/backend/src/app.ts index 6ee359ff..e97765a1 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -2,7 +2,7 @@ import { json } from "body-parser"; import express from "express"; import mongoose from "mongoose"; -// import userRoute from './routes/userRoute' +import userRoute from './routes/userRoute' import { mongoURI, port } from "./config"; @@ -16,6 +16,7 @@ class Server { // initialize server app const server = new Server(); +// Connect to MongoDB void mongoose .connect(mongoURI) .then(() => { @@ -25,8 +26,12 @@ void mongoose console.log(error); }); +// Middleware server.app.use(json()); +// Routes +server.app.use(userRoute); + // make server listen on some port server.app.listen(port, () => { console.log(`> Listening on port ${port}`); diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 747fb4ea..ccb3b5ed 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -6,9 +6,9 @@ import mongoose, { Document } from "mongoose"; export type UserDocument = { name: string; gender: string; - accountType: "admin" | "team"; - approvalStatus: string; // Should this be restricted to certain values? - firebaseUid: string; + accountType: "admin" | "team"; // TODO Can be stored on Firebase using Custom Claims + approvalStatus: string; // TODO Should this be restricted to certain values? + firebaseUid: string; // Linkage between firebase account and user document on MongoDb } & Document; const userSchema = new mongoose.Schema({ diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index e69de29b..e469455a 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -0,0 +1,38 @@ +// userRoute.ts +import express, { Request, Response } from 'express'; +import User from '../models/User'; // Adjust the path based on your project structure +import admin from 'firebase-admin'; + +const router = express.Router(); + +router.use(express.json()); + +router.post('/api/createUser', async (req: Request, res: Response) => { + try { + const { name, gender, accountType, approvalStatus } = req.body; + + // Create user in Firebase Authentication + const userRecord = await admin.auth().createUser({ + email: req.body.email, + password: req.body.password, + }); + + // Create user in MongoDB with additional details + const newUser = new User({ + name, + gender, + accountType, + approvalStatus, + firebaseUid: userRecord.uid, + }); + + await newUser.save(); + + res.status(201).json({ message: 'User created successfully' }); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +export default router; From c519487eeac525d7960c6ac2294d7eb9d709c36f Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 08:29:29 -0800 Subject: [PATCH 03/38] Initialize Firebase Admin SDK --- backend/src/routes/userRoute.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index e469455a..b43f0325 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,20 +1,28 @@ -// userRoute.ts import express, { Request, Response } from 'express'; -import User from '../models/User'; // Adjust the path based on your project structure +import User from '../models/User'; import admin from 'firebase-admin'; +import path from 'path'; const router = express.Router(); +// Initialize Firebase Admin SDK +const serviceAccountPath = path.resolve(__dirname, '../../firebase/fb_service_account_key.json'); +const serviceAccount = require(serviceAccountPath); +admin.initializeApp({ + credential: admin.credential.cert(serviceAccount), + databaseURL: process.env.FIREBASE_DATABASE_URL, +}); + router.use(express.json()); router.post('/api/createUser', async (req: Request, res: Response) => { try { - const { name, gender, accountType, approvalStatus } = req.body; + const { name, gender, accountType, approvalStatus, email, password } = req.body; // Create user in Firebase Authentication const userRecord = await admin.auth().createUser({ - email: req.body.email, - password: req.body.password, + email, + password, }); // Create user in MongoDB with additional details From 534571a6625695313920cec3871fd15b009d6cfa Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 08:40:30 -0800 Subject: [PATCH 04/38] Add ServiceAccountKey.json to .gitignore --- backend/.gitignore | 3 +++ backend/src/routes/userRoute.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/.gitignore b/backend/.gitignore index 552d1bbb..cbba7d16 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,3 +1,6 @@ +# Firebase Service Account Key +src/firebase/ServiceAccountKey.json + .env node_modules/ .eslintcache diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index b43f0325..d4913e53 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -6,7 +6,7 @@ import path from 'path'; const router = express.Router(); // Initialize Firebase Admin SDK -const serviceAccountPath = path.resolve(__dirname, '../../firebase/fb_service_account_key.json'); +const serviceAccountPath = path.resolve(__dirname, '../../firebase/ServiceAccountKey.json'); const serviceAccount = require(serviceAccountPath); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), From 1fc947066313b33b92f2236de9838dde24984b30 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 08:47:14 -0800 Subject: [PATCH 05/38] Formatting --- backend/src/app.ts | 3 +-- backend/src/models/User.ts | 4 ++-- backend/src/routes/userRoute.ts | 24 +++++++++++++----------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/backend/src/app.ts b/backend/src/app.ts index e97765a1..3eb16fd4 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -2,9 +2,8 @@ import { json } from "body-parser"; import express from "express"; import mongoose from "mongoose"; -import userRoute from './routes/userRoute' - import { mongoURI, port } from "./config"; +import userRoute from "./routes/userRoute"; /** * Express server application class diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index ccb3b5ed..c40a8415 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -6,9 +6,9 @@ import mongoose, { Document } from "mongoose"; export type UserDocument = { name: string; gender: string; - accountType: "admin" | "team"; // TODO Can be stored on Firebase using Custom Claims + accountType: "admin" | "team"; // TODO Can be stored on Firebase using Custom Claims approvalStatus: string; // TODO Should this be restricted to certain values? - firebaseUid: string; // Linkage between firebase account and user document on MongoDb + firebaseUid: string; // Linkage between firebase account and user document on MongoDb } & Document; const userSchema = new mongoose.Schema({ diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index d4913e53..9e5ac263 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,12 +1,14 @@ -import express, { Request, Response } from 'express'; -import User from '../models/User'; -import admin from 'firebase-admin'; -import path from 'path'; +import path from "path"; + +import express, { Request, Response } from "express"; +import admin from "firebase-admin"; + +import User from "../models/User"; const router = express.Router(); -// Initialize Firebase Admin SDK -const serviceAccountPath = path.resolve(__dirname, '../../firebase/ServiceAccountKey.json'); +// Initialize Firebase Admin SDK +const serviceAccountPath = path.resolve(__dirname, "../../firebase/ServiceAccountKey.json"); const serviceAccount = require(serviceAccountPath); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), @@ -15,17 +17,17 @@ admin.initializeApp({ router.use(express.json()); -router.post('/api/createUser', async (req: Request, res: Response) => { +router.post("/api/createUser", async (req: Request, res: Response) => { try { const { name, gender, accountType, approvalStatus, email, password } = req.body; - // Create user in Firebase Authentication + // Create user in Firebase const userRecord = await admin.auth().createUser({ email, password, }); - // Create user in MongoDB with additional details + // Create user in MongoDB const newUser = new User({ name, gender, @@ -36,10 +38,10 @@ router.post('/api/createUser', async (req: Request, res: Response) => { await newUser.save(); - res.status(201).json({ message: 'User created successfully' }); + res.status(201).json({ message: "User created successfully" }); } catch (error) { console.error(error); - res.status(500).json({ error: 'Internal server error' }); + res.status(500).json({ error: "Internal server error" }); } }); From d8b2cf52dc35b5b7576923f6edc92c332e260b04 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 10:13:49 -0800 Subject: [PATCH 06/38] revert changes --- backend/src/routes/userRoute.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 9e5ac263..efa74868 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,5 +1,3 @@ -import path from "path"; - import express, { Request, Response } from "express"; import admin from "firebase-admin"; @@ -8,8 +6,7 @@ import User from "../models/User"; const router = express.Router(); // Initialize Firebase Admin SDK -const serviceAccountPath = path.resolve(__dirname, "../../firebase/ServiceAccountKey.json"); -const serviceAccount = require(serviceAccountPath); +const serviceAccount = require("../../firebase/ServiceAccountKey.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: process.env.FIREBASE_DATABASE_URL, From 62add2538cd1ce566f690456b3ae9d4500b06716 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 10:36:39 -0800 Subject: [PATCH 07/38] Store account type on firebase using Custom Claims --- backend/src/models/User.ts | 4 ++-- backend/src/routes/userRoute.ts | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index c40a8415..7bf3d08a 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -6,8 +6,8 @@ import mongoose, { Document } from "mongoose"; export type UserDocument = { name: string; gender: string; - accountType: "admin" | "team"; // TODO Can be stored on Firebase using Custom Claims - approvalStatus: string; // TODO Should this be restricted to certain values? + accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims + approvalStatus: string; // NOTE Should this be restricted to certain values? firebaseUid: string; // Linkage between firebase account and user document on MongoDb } & Document; diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index efa74868..1d58b31c 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -6,7 +6,7 @@ import User from "../models/User"; const router = express.Router(); // Initialize Firebase Admin SDK -const serviceAccount = require("../../firebase/ServiceAccountKey.json"); +const serviceAccount = require("../../firebase/ServiceAccountKey.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: process.env.FIREBASE_DATABASE_URL, @@ -14,17 +14,20 @@ admin.initializeApp({ router.use(express.json()); -router.post("/api/createUser", async (req: Request, res: Response) => { +router.post("/createUser", async (req: Request, res: Response) => { try { const { name, gender, accountType, approvalStatus, email, password } = req.body; - // Create user in Firebase + // Create user in Firebase const userRecord = await admin.auth().createUser({ email, password, }); - // Create user in MongoDB + // Set custom claim for accountType (“admin” | “team”) + await admin.auth().setCustomUserClaims(userRecord.uid, { accountType }); + + // Create user in MongoDB const newUser = new User({ name, gender, From 0308ccc56a1a091e2f001beffbe7272e61af9b68 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 11:12:39 -0800 Subject: [PATCH 08/38] Fix relative path --- backend/src/routes/userRoute.ts | 9 ++++++--- backend/tsconfig.json | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 1d58b31c..4eb448c1 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,20 +1,23 @@ + import express, { Request, Response } from "express"; -import admin from "firebase-admin"; +import admin, { ServiceAccount } from "firebase-admin"; import User from "../models/User"; + const router = express.Router(); // Initialize Firebase Admin SDK -const serviceAccount = require("../../firebase/ServiceAccountKey.json"); +const serviceAccount = require("../firebase/ServiceAccountKey.json") as ServiceAccount; admin.initializeApp({ - credential: admin.credential.cert(serviceAccount), + credential: admin.credential.cert(serviceAccount), // Use type assertion databaseURL: process.env.FIREBASE_DATABASE_URL, }); router.use(express.json()); router.post("/createUser", async (req: Request, res: Response) => { +// router.post("/createUser", async (req: Request, res: Response): Promise => { try { const { name, gender, accountType, approvalStatus, email, password } = req.body; diff --git a/backend/tsconfig.json b/backend/tsconfig.json index bb2f7f66..7a4e63ab 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -39,7 +39,7 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ From 2962be9d7cf39b0d2583b0c74fd326a7609db06c Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 11:59:59 -0800 Subject: [PATCH 09/38] Resolved most lint check errors --- backend/src/routes/userRoute.ts | 91 +++++++++++++++++++++------------ backend/tsconfig.json | 2 +- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 4eb448c1..1f0620a1 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -2,50 +2,73 @@ import express, { Request, Response } from "express"; import admin, { ServiceAccount } from "firebase-admin"; -import User from "../models/User"; +import * as serviceAccount from "../firebase/ServiceAccountKey.json"; +import User, { UserDocument } from "../models/User"; +// Define the type for req.body +type CreateUserRequestBody = { + name: string; + gender: string; + accountType: "admin" | "team"; + approvalStatus: string; // NOTE Should this be restricted to certain values? + email: string; + password: string; +}; const router = express.Router(); // Initialize Firebase Admin SDK -const serviceAccount = require("../firebase/ServiceAccountKey.json") as ServiceAccount; +// const serviceAccount = require("../firebase/ServiceAccountKey.json") as ServiceAccount; admin.initializeApp({ - credential: admin.credential.cert(serviceAccount), // Use type assertion + // credential: admin.credential.cert(serviceAccount), // Type assertion + credential: admin.credential.cert(serviceAccount as ServiceAccount), // Type assertion databaseURL: process.env.FIREBASE_DATABASE_URL, }); router.use(express.json()); -router.post("/createUser", async (req: Request, res: Response) => { -// router.post("/createUser", async (req: Request, res: Response): Promise => { - try { - const { name, gender, accountType, approvalStatus, email, password } = req.body; - - // Create user in Firebase - const userRecord = await admin.auth().createUser({ - email, - password, - }); - - // Set custom claim for accountType (“admin” | “team”) - await admin.auth().setCustomUserClaims(userRecord.uid, { accountType }); - - // Create user in MongoDB - const newUser = new User({ - name, - gender, - accountType, - approvalStatus, - firebaseUid: userRecord.uid, - }); - - await newUser.save(); - - res.status(201).json({ message: "User created successfully" }); - } catch (error) { - console.error(error); - res.status(500).json({ error: "Internal server error" }); - } -}); +// router.post("/createUser", async (req: Request, Record, CreateUserRequestBody>, res: Response) => { +// router.post("/createUser", async (req: Request<{}, {}, CreateUserRequestBody>, res: Response) => { +router.post( + "/createUser", + async ( + req: Request, Record, CreateUserRequestBody>, + res: Response, + // ) => { + ): Promise => { + + try { + const { name, gender, accountType, approvalStatus, email, password } = req.body; + + // Create user in Firebase + const userRecord = await admin.auth().createUser({ + email, + password, + } as admin.auth.CreateRequest); // Type assertion + + // Set custom claim for accountType (“admin” | “team”) + await admin.auth().setCustomUserClaims(userRecord.uid, { accountType }); + + // Create user in MongoDB + const newUser = new User({ + name, + gender, + accountType, + approvalStatus, + firebaseUid: userRecord.uid, + } as UserDocument); // Type assertion + + await newUser.save(); + + res.status(201).json({ message: "User created successfully" }); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } + + return; + }, +); export default router; + diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 7a4e63ab..b1b1546d 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -39,7 +39,7 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true /* Enable importing .json files. */, // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ From 29580a5e40a8903a3a168f8502c6b5399c399aa6 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 12:12:50 -0800 Subject: [PATCH 10/38] Remove unecessary comments --- backend/src/models/User.ts | 3 --- backend/src/routes/userRoute.ts | 8 ++------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 7bf3d08a..5b9800c6 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -1,8 +1,5 @@ import mongoose, { Document } from "mongoose"; -// email and password stored in Firebase -// name, gender, account type (Admin/Team), and approval status stored in MongoDB - export type UserDocument = { name: string; gender: string; diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 1f0620a1..649e38c8 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -18,24 +18,20 @@ type CreateUserRequestBody = { const router = express.Router(); // Initialize Firebase Admin SDK -// const serviceAccount = require("../firebase/ServiceAccountKey.json") as ServiceAccount; admin.initializeApp({ - // credential: admin.credential.cert(serviceAccount), // Type assertion credential: admin.credential.cert(serviceAccount as ServiceAccount), // Type assertion databaseURL: process.env.FIREBASE_DATABASE_URL, }); router.use(express.json()); -// router.post("/createUser", async (req: Request, Record, CreateUserRequestBody>, res: Response) => { -// router.post("/createUser", async (req: Request<{}, {}, CreateUserRequestBody>, res: Response) => { router.post( "/createUser", async ( req: Request, Record, CreateUserRequestBody>, res: Response, - // ) => { - ): Promise => { + // ): Promise => { + ) => { try { const { name, gender, accountType, approvalStatus, email, password } = req.body; From c314277deca3c803e6b62235c59a5c9ab6ec233f Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 17 Jan 2024 12:21:38 -0800 Subject: [PATCH 11/38] Resolve lint check errors --- backend/.eslintrc.json | 2 ++ backend/src/routes/userRoute.ts | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/backend/.eslintrc.json b/backend/.eslintrc.json index 6c9c68a1..746e2c5c 100644 --- a/backend/.eslintrc.json +++ b/backend/.eslintrc.json @@ -37,6 +37,8 @@ // "@typescript-eslint/ban-ts-comment": "off", // "@typescript-eslint/no-explicit-any": "off", // "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-misused-promises": "warn", + "@typescript-eslint/require-await": "warn", // Avoid bugs. "@typescript-eslint/no-shadow": ["error", { "ignoreTypeValueShadow": true }], diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 649e38c8..93cb1ac6 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,4 +1,3 @@ - import express, { Request, Response } from "express"; import admin, { ServiceAccount } from "firebase-admin"; @@ -30,9 +29,7 @@ router.post( async ( req: Request, Record, CreateUserRequestBody>, res: Response, - // ): Promise => { - ) => { - + ) => { try { const { name, gender, accountType, approvalStatus, email, password } = req.body; @@ -67,4 +64,3 @@ router.post( ); export default router; - From f1c99025b5fe0d2a1d1de9f042a6190d10a09250 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Tue, 23 Jan 2024 23:17:03 -0800 Subject: [PATCH 12/38] Add .keep file to firebase directory --- backend/src/firebase/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 backend/src/firebase/.keep diff --git a/backend/src/firebase/.keep b/backend/src/firebase/.keep new file mode 100644 index 00000000..e69de29b From de0b62fb838153c8366d61a4e14fbf38325d4ca0 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Tue, 23 Jan 2024 23:28:03 -0800 Subject: [PATCH 13/38] Add service account as env variable and import in ./config.ts --- backend/src/config.ts | 10 +++++++++- backend/src/errors/internal.ts | 3 +++ backend/src/routes/userRoute.ts | 5 +++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/src/config.ts b/backend/src/config.ts index ecd057c6..b489c927 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -7,6 +7,7 @@ dotenv.config({ path: ".env" }); let portV = ""; let mongoV = ""; +let serviceAccountKeyV = ""; if (!process.env.APP_PORT) { throw InternalError.NO_APP_PORT; @@ -20,11 +21,18 @@ if (!process.env.MONGO_URI) { mongoV = process.env.MONGO_URI; } +if (!process.env.SERVICE_ACCOUNT_KEY) { + throw InternalError.NO_SERVICE_ACCOUNT_KEY; +} else { + serviceAccountKeyV = process.env.SERVICE_ACCOUNT_KEY; +} + /** * Have to do this workaround since lint doesn't let * us export vars */ const port = portV; const mongoURI = mongoV; +const serviceAccountKey = serviceAccountKeyV; -export { port, mongoURI }; +export { port, mongoURI, serviceAccountKey }; diff --git a/backend/src/errors/internal.ts b/backend/src/errors/internal.ts index 5c86c9a0..424cea9f 100644 --- a/backend/src/errors/internal.ts +++ b/backend/src/errors/internal.ts @@ -2,9 +2,12 @@ import { CustomError } from "./errors"; const NO_APP_PORT = "Could not find app port env variable"; const NO_MONGO_URI = "Could not find mongo uri env variable"; +const NO_SERVICE_ACCOUNT_KEY = "Could not find service account key env variable"; export class InternalError extends CustomError { static NO_APP_PORT = new InternalError(0, 500, NO_APP_PORT); static NO_MONGO_URI = new InternalError(1, 500, NO_MONGO_URI); + + static NO_SERVICE_ACCOUNT_KEY = new InternalError(2, 500, NO_SERVICE_ACCOUNT_KEY); } diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 93cb1ac6..d29ab19f 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,7 +1,8 @@ import express, { Request, Response } from "express"; import admin, { ServiceAccount } from "firebase-admin"; -import * as serviceAccount from "../firebase/ServiceAccountKey.json"; +import { serviceAccountKey } from "../config"; + import User, { UserDocument } from "../models/User"; // Define the type for req.body @@ -18,7 +19,7 @@ const router = express.Router(); // Initialize Firebase Admin SDK admin.initializeApp({ - credential: admin.credential.cert(serviceAccount as ServiceAccount), // Type assertion + credential: admin.credential.cert(serviceAccountKey as ServiceAccount), // Type assertion databaseURL: process.env.FIREBASE_DATABASE_URL, }); From 2af5b2d457fba7a0248df4fcdd618d482d309e1e Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Tue, 23 Jan 2024 23:33:20 -0800 Subject: [PATCH 14/38] Change approvalStatus type from string to boolean --- backend/src/models/User.ts | 4 ++-- backend/src/routes/userRoute.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 5b9800c6..9203d599 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -4,7 +4,7 @@ export type UserDocument = { name: string; gender: string; accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims - approvalStatus: string; // NOTE Should this be restricted to certain values? + approvalStatus: boolean; firebaseUid: string; // Linkage between firebase account and user document on MongoDb } & Document; @@ -12,7 +12,7 @@ const userSchema = new mongoose.Schema({ name: { type: String, required: true }, gender: { type: String, required: true }, accountType: { type: String, enum: ["admin", "team"], required: true }, - approvalStatus: { type: String, required: true }, + approvalStatus: { type: Boolean, required: true }, firebaseUid: { type: String, required: true }, }); diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index d29ab19f..e55093d8 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -2,7 +2,6 @@ import express, { Request, Response } from "express"; import admin, { ServiceAccount } from "firebase-admin"; import { serviceAccountKey } from "../config"; - import User, { UserDocument } from "../models/User"; // Define the type for req.body @@ -10,7 +9,7 @@ type CreateUserRequestBody = { name: string; gender: string; accountType: "admin" | "team"; - approvalStatus: string; // NOTE Should this be restricted to certain values? + approvalStatus: boolean; email: string; password: string; }; From fcd216a95ee196efb65285c862464c882a340dbf Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Tue, 23 Jan 2024 23:50:24 -0800 Subject: [PATCH 15/38] Set User document id to corresponding firebase id instead of storing firebase uid in document --- backend/src/models/User.ts | 3 +-- backend/src/routes/userRoute.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 9203d599..fc26b03e 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -5,15 +5,14 @@ export type UserDocument = { gender: string; accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims approvalStatus: boolean; - firebaseUid: string; // Linkage between firebase account and user document on MongoDb } & Document; const userSchema = new mongoose.Schema({ + _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb name: { type: String, required: true }, gender: { type: String, required: true }, accountType: { type: String, enum: ["admin", "team"], required: true }, approvalStatus: { type: Boolean, required: true }, - firebaseUid: { type: String, required: true }, }); export default mongoose.model("User", userSchema); diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index e55093d8..69cf8d3f 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -44,11 +44,11 @@ router.post( // Create user in MongoDB const newUser = new User({ + _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, gender, accountType, approvalStatus, - firebaseUid: userRecord.uid, } as UserDocument); // Type assertion await newUser.save(); From c348b441085822db0cdd1b343bb68e580578a642 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 24 Jan 2024 00:18:20 -0800 Subject: [PATCH 16/38] Create firebase config file --- backend/src/firebase/firebase_config.ts | 11 +++++++++++ backend/src/models/User.ts | 2 +- backend/src/routes/userRoute.ts | 16 +++++----------- 3 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 backend/src/firebase/firebase_config.ts diff --git a/backend/src/firebase/firebase_config.ts b/backend/src/firebase/firebase_config.ts new file mode 100644 index 00000000..c754f542 --- /dev/null +++ b/backend/src/firebase/firebase_config.ts @@ -0,0 +1,11 @@ +import admin, { ServiceAccount } from "firebase-admin"; + +import { serviceAccountKey } from "../config"; + +// Initialize Firebase Admin SDK to store user credentials +admin.initializeApp({ + credential: admin.credential.cert(serviceAccountKey as ServiceAccount), // Type assertion +}); + +// Export firebase auth object to make accessible to other files +export const firebaseAuth = admin.auth(); diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index fc26b03e..a22452c9 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -8,7 +8,7 @@ export type UserDocument = { } & Document; const userSchema = new mongoose.Schema({ - _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb + _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb name: { type: String, required: true }, gender: { type: String, required: true }, accountType: { type: String, enum: ["admin", "team"], required: true }, diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 69cf8d3f..8db99161 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,7 +1,7 @@ import express, { Request, Response } from "express"; -import admin, { ServiceAccount } from "firebase-admin"; +import admin from "firebase-admin"; -import { serviceAccountKey } from "../config"; +import { firebaseAuth } from "../firebase/firebase_config"; import User, { UserDocument } from "../models/User"; // Define the type for req.body @@ -16,12 +16,6 @@ type CreateUserRequestBody = { const router = express.Router(); -// Initialize Firebase Admin SDK -admin.initializeApp({ - credential: admin.credential.cert(serviceAccountKey as ServiceAccount), // Type assertion - databaseURL: process.env.FIREBASE_DATABASE_URL, -}); - router.use(express.json()); router.post( @@ -34,17 +28,17 @@ router.post( const { name, gender, accountType, approvalStatus, email, password } = req.body; // Create user in Firebase - const userRecord = await admin.auth().createUser({ + const userRecord = await firebaseAuth.createUser({ email, password, } as admin.auth.CreateRequest); // Type assertion // Set custom claim for accountType (“admin” | “team”) - await admin.auth().setCustomUserClaims(userRecord.uid, { accountType }); + await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); // Create user in MongoDB const newUser = new User({ - _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) + _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, gender, accountType, From 3fd3b18e23659df6477e65a82970fa4732cef8c9 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 24 Jan 2024 01:09:49 -0800 Subject: [PATCH 17/38] Move createUser function from routes directory to controller directory --- backend/src/controllers/userController.ts | 51 +++++++++++++++++++++ backend/src/routes/userRoute.ts | 55 ++--------------------- backend/src/validators/userValidator.ts | 0 3 files changed, 54 insertions(+), 52 deletions(-) create mode 100644 backend/src/controllers/userController.ts create mode 100644 backend/src/validators/userValidator.ts diff --git a/backend/src/controllers/userController.ts b/backend/src/controllers/userController.ts new file mode 100644 index 00000000..1dc0f22a --- /dev/null +++ b/backend/src/controllers/userController.ts @@ -0,0 +1,51 @@ +import { Request, Response } from "express"; +import admin from "firebase-admin"; + +import { firebaseAuth } from "../firebase/firebase_config"; +import User, { UserDocument } from "../models/User"; + +// Define the type for req.body +type CreateUserRequestBody = { + name: string; + gender: string; + accountType: "admin" | "team"; + approvalStatus: boolean; + email: string; + password: string; +}; + +export const createUser = async ( + req: Request, Record, CreateUserRequestBody>, + res: Response, +) => { + try { + const { name, gender, accountType, approvalStatus, email, password } = req.body; + + // Create user in Firebase + const userRecord = await firebaseAuth.createUser({ + email, + password, + } as admin.auth.CreateRequest); // Type assertion + + // Set custom claim for accountType (“admin” | “team”) + await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); + + // Create user in MongoDB + const newUser = new User({ + _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) + name, + gender, + accountType, + approvalStatus, + } as UserDocument); // Type assertion + + await newUser.save(); + + res.status(201).json({ message: "User created successfully" }); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } + + return; +}; diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index 8db99161..a0f6413f 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -1,60 +1,11 @@ -import express, { Request, Response } from "express"; -import admin from "firebase-admin"; +import express from "express"; -import { firebaseAuth } from "../firebase/firebase_config"; -import User, { UserDocument } from "../models/User"; - -// Define the type for req.body -type CreateUserRequestBody = { - name: string; - gender: string; - accountType: "admin" | "team"; - approvalStatus: boolean; - email: string; - password: string; -}; +import { createUser } from "../controllers/userController"; const router = express.Router(); router.use(express.json()); -router.post( - "/createUser", - async ( - req: Request, Record, CreateUserRequestBody>, - res: Response, - ) => { - try { - const { name, gender, accountType, approvalStatus, email, password } = req.body; - - // Create user in Firebase - const userRecord = await firebaseAuth.createUser({ - email, - password, - } as admin.auth.CreateRequest); // Type assertion - - // Set custom claim for accountType (“admin” | “team”) - await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); - - // Create user in MongoDB - const newUser = new User({ - _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) - name, - gender, - accountType, - approvalStatus, - } as UserDocument); // Type assertion - - await newUser.save(); - - res.status(201).json({ message: "User created successfully" }); - } catch (error) { - console.error(error); - res.status(500).json({ error: "Internal server error" }); - } - - return; - }, -); +router.post("/createUser", createUser); export default router; diff --git a/backend/src/validators/userValidator.ts b/backend/src/validators/userValidator.ts new file mode 100644 index 00000000..e69de29b From de6a732836be48a1d66eee016565edb7b32a9925 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 24 Jan 2024 01:37:33 -0800 Subject: [PATCH 18/38] Use custom error handler to handle errors --- backend/src/app.ts | 8 ++++++-- backend/src/controllers/userController.ts | 4 +++- backend/src/errors/index.ts | 1 + backend/src/errors/user.ts | 7 +++++++ backend/src/routes/userRoute.ts | 2 +- 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 backend/src/errors/user.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index 3eb16fd4..922e88f6 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -3,7 +3,8 @@ import express from "express"; import mongoose from "mongoose"; import { mongoURI, port } from "./config"; -import userRoute from "./routes/userRoute"; +import { userRouter } from "./routes/userRoute"; +import { errorHandler } from "./errors/handler"; /** * Express server application class @@ -29,7 +30,10 @@ void mongoose server.app.use(json()); // Routes -server.app.use(userRoute); +server.app.use(userRouter); + +// Error Handler +server.app.use(errorHandler); // make server listen on some port server.app.listen(port, () => { diff --git a/backend/src/controllers/userController.ts b/backend/src/controllers/userController.ts index 1dc0f22a..90d87d55 100644 --- a/backend/src/controllers/userController.ts +++ b/backend/src/controllers/userController.ts @@ -3,6 +3,8 @@ import admin from "firebase-admin"; import { firebaseAuth } from "../firebase/firebase_config"; import User, { UserDocument } from "../models/User"; +import { UserError } from "../errors"; +import { errorHandler } from "../errors/handler"; // Define the type for req.body type CreateUserRequestBody = { @@ -44,7 +46,7 @@ export const createUser = async ( res.status(201).json({ message: "User created successfully" }); } catch (error) { console.error(error); - res.status(500).json({ error: "Internal server error" }); + errorHandler(UserError.USER_CREATION_UNSUCCESSFUL, req, res); } return; diff --git a/backend/src/errors/index.ts b/backend/src/errors/index.ts index 0855cdc4..0972f898 100644 --- a/backend/src/errors/index.ts +++ b/backend/src/errors/index.ts @@ -1,2 +1,3 @@ export * from "./errors"; export * from "./internal"; +export * from "./user"; diff --git a/backend/src/errors/user.ts b/backend/src/errors/user.ts new file mode 100644 index 00000000..679b7c4e --- /dev/null +++ b/backend/src/errors/user.ts @@ -0,0 +1,7 @@ +import { CustomError } from "./errors"; + +const USER_CREATION_UNSUCCESSFUL = "User not created successfully"; + +export class UserError extends CustomError { + static USER_CREATION_UNSUCCESSFUL = new UserError(0, 400, USER_CREATION_UNSUCCESSFUL); +} diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts index a0f6413f..ab8ec60e 100644 --- a/backend/src/routes/userRoute.ts +++ b/backend/src/routes/userRoute.ts @@ -8,4 +8,4 @@ router.use(express.json()); router.post("/createUser", createUser); -export default router; +export { router as userRouter }; From 150ab281db1a8761f87cf03e2db1a54232387db3 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 24 Jan 2024 02:00:33 -0800 Subject: [PATCH 19/38] Check req body using express-validator and createUser validator function --- backend/package-lock.json | 26 +++++++++++++++++++ backend/package.json | 1 + backend/src/app.ts | 2 +- .../{userController.ts => user.ts} | 19 ++++++++++++-- backend/src/errors/user.ts | 2 +- backend/src/routes/user.ts | 12 +++++++++ backend/src/routes/userRoute.ts | 11 -------- backend/src/validators/user.ts | 10 +++++++ backend/src/validators/userValidator.ts | 0 9 files changed, 68 insertions(+), 15 deletions(-) rename backend/src/controllers/{userController.ts => user.ts} (77%) create mode 100644 backend/src/routes/user.ts delete mode 100644 backend/src/routes/userRoute.ts create mode 100644 backend/src/validators/user.ts delete mode 100644 backend/src/validators/userValidator.ts diff --git a/backend/package-lock.json b/backend/package-lock.json index b4fd8036..e41ece62 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -12,6 +12,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "express-validator": "^7.0.1", "firebase-admin": "^12.0.0", "mongodb": "^6.3.0", "mongoose": "^8.0.3" @@ -2387,6 +2388,18 @@ "node": ">= 0.10.0" } }, + "node_modules/express-validator": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz", + "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==", + "dependencies": { + "lodash": "^4.17.21", + "validator": "^13.9.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3765,6 +3778,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -5601,6 +5619,14 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/backend/package.json b/backend/package.json index eb8663e1..c5ad2caf 100644 --- a/backend/package.json +++ b/backend/package.json @@ -18,6 +18,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "express-validator": "^7.0.1", "firebase-admin": "^12.0.0", "mongodb": "^6.3.0", "mongoose": "^8.0.3" diff --git a/backend/src/app.ts b/backend/src/app.ts index 922e88f6..4fb39517 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -3,8 +3,8 @@ import express from "express"; import mongoose from "mongoose"; import { mongoURI, port } from "./config"; -import { userRouter } from "./routes/userRoute"; import { errorHandler } from "./errors/handler"; +import { userRouter } from "./routes/user"; /** * Express server application class diff --git a/backend/src/controllers/userController.ts b/backend/src/controllers/user.ts similarity index 77% rename from backend/src/controllers/userController.ts rename to backend/src/controllers/user.ts index 90d87d55..092425f6 100644 --- a/backend/src/controllers/userController.ts +++ b/backend/src/controllers/user.ts @@ -1,10 +1,11 @@ import { Request, Response } from "express"; +import { validationResult } from "express-validator"; import admin from "firebase-admin"; -import { firebaseAuth } from "../firebase/firebase_config"; -import User, { UserDocument } from "../models/User"; import { UserError } from "../errors"; import { errorHandler } from "../errors/handler"; +import { firebaseAuth } from "../firebase/firebase_config"; +import User, { UserDocument } from "../models/User"; // Define the type for req.body type CreateUserRequestBody = { @@ -21,6 +22,20 @@ export const createUser = async ( res: Response, ) => { try { + // Check for validation errors + const errors = validationResult(req); + // if (!errors.isEmpty()) { + // return res.status(400).json({ errors: errors.array() }); + // } + if (!errors.isEmpty()) { + let errStr = ""; + for (const err of errors.array()) { + errStr += err.msg + " "; + } + errStr = errStr.trim(); + throw new UserError(0, 400, errStr); + } + const { name, gender, accountType, approvalStatus, email, password } = req.body; // Create user in Firebase diff --git a/backend/src/errors/user.ts b/backend/src/errors/user.ts index 679b7c4e..2b095f0d 100644 --- a/backend/src/errors/user.ts +++ b/backend/src/errors/user.ts @@ -3,5 +3,5 @@ import { CustomError } from "./errors"; const USER_CREATION_UNSUCCESSFUL = "User not created successfully"; export class UserError extends CustomError { - static USER_CREATION_UNSUCCESSFUL = new UserError(0, 400, USER_CREATION_UNSUCCESSFUL); + static USER_CREATION_UNSUCCESSFUL = new UserError(1, 400, USER_CREATION_UNSUCCESSFUL); } diff --git a/backend/src/routes/user.ts b/backend/src/routes/user.ts new file mode 100644 index 00000000..0546a63a --- /dev/null +++ b/backend/src/routes/user.ts @@ -0,0 +1,12 @@ +import express from "express"; + +import * as UserController from "../controllers/user"; +import * as UserValidator from "../validators/user"; + +const router = express.Router(); + +router.use(express.json()); + +router.post("/", UserValidator.createUser, UserController.createUser); + +export { router as userRouter }; diff --git a/backend/src/routes/userRoute.ts b/backend/src/routes/userRoute.ts deleted file mode 100644 index ab8ec60e..00000000 --- a/backend/src/routes/userRoute.ts +++ /dev/null @@ -1,11 +0,0 @@ -import express from "express"; - -import { createUser } from "../controllers/userController"; - -const router = express.Router(); - -router.use(express.json()); - -router.post("/createUser", createUser); - -export { router as userRouter }; diff --git a/backend/src/validators/user.ts b/backend/src/validators/user.ts new file mode 100644 index 00000000..fcb26be0 --- /dev/null +++ b/backend/src/validators/user.ts @@ -0,0 +1,10 @@ +import { ValidationChain, body } from "express-validator"; + +export const createUser: ValidationChain[] = [ + body("name").notEmpty().isString(), + body("gender").notEmpty().isString(), + body("accountType").notEmpty().isIn(["admin", "team"]), + body("approvalStatus").notEmpty().isBoolean(), + body("email").notEmpty().isEmail(), + body("password").notEmpty().isString().isLength({ min: 6 }), +]; diff --git a/backend/src/validators/userValidator.ts b/backend/src/validators/userValidator.ts deleted file mode 100644 index e69de29b..00000000 From f6b92332a50564cf2e11e255373a2cd301e865eb Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 24 Jan 2024 12:33:58 -0800 Subject: [PATCH 20/38] Remove gender field from User --- backend/src/controllers/user.ts | 4 +--- backend/src/models/User.ts | 2 -- backend/src/validators/user.ts | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 092425f6..e7a49982 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -10,7 +10,6 @@ import User, { UserDocument } from "../models/User"; // Define the type for req.body type CreateUserRequestBody = { name: string; - gender: string; accountType: "admin" | "team"; approvalStatus: boolean; email: string; @@ -36,7 +35,7 @@ export const createUser = async ( throw new UserError(0, 400, errStr); } - const { name, gender, accountType, approvalStatus, email, password } = req.body; + const { name, accountType, approvalStatus, email, password } = req.body; // Create user in Firebase const userRecord = await firebaseAuth.createUser({ @@ -51,7 +50,6 @@ export const createUser = async ( const newUser = new User({ _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, - gender, accountType, approvalStatus, } as UserDocument); // Type assertion diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index a22452c9..590b6b08 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -2,7 +2,6 @@ import mongoose, { Document } from "mongoose"; export type UserDocument = { name: string; - gender: string; accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims approvalStatus: boolean; } & Document; @@ -10,7 +9,6 @@ export type UserDocument = { const userSchema = new mongoose.Schema({ _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb name: { type: String, required: true }, - gender: { type: String, required: true }, accountType: { type: String, enum: ["admin", "team"], required: true }, approvalStatus: { type: Boolean, required: true }, }); diff --git a/backend/src/validators/user.ts b/backend/src/validators/user.ts index fcb26be0..556306d3 100644 --- a/backend/src/validators/user.ts +++ b/backend/src/validators/user.ts @@ -2,7 +2,6 @@ import { ValidationChain, body } from "express-validator"; export const createUser: ValidationChain[] = [ body("name").notEmpty().isString(), - body("gender").notEmpty().isString(), body("accountType").notEmpty().isIn(["admin", "team"]), body("approvalStatus").notEmpty().isBoolean(), body("email").notEmpty().isEmail(), From dd4a4350dcfb9a2fd4f0ff9855e9fe6e3764092c Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 09:39:15 -0800 Subject: [PATCH 21/38] Fixed route --- .DS_Store | Bin 0 -> 8196 bytes backend/.DS_Store | Bin 0 -> 6148 bytes backend/src/app.ts | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 backend/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1bed5bce617e260d7b7a425e8a3fec25ad2aeb1f GIT binary patch literal 8196 zcmeHML2DC16n@jjX46)QP@zzSMNtrHO$)_}mo!Ze1@+J^DyY6V=t1y@c+&S~reQMM^eCb;F!Oe2zW3(6Z)SG$HUPj1t;#IG zBmg*ANoL2e*{9Gr)kGOmJyR$d>cdLN%YMjxyw4`kw!<=D8L$jk1}p=Xfxm$Pd}mW} z2E6y>sBJ9+mVy700eU{TSV`uU>`Eyf9oUEz0A&ihMZs(F(;uZv9VqikcBRA~EKI7R zl&Van7))gjOseB}Ug5h^N_AjjX0)SbW-3ErD)C^hfCI}*XC zHuCpH9Gm$iicsv~!i`z4%xiVgJAU-8ZllJFMfDB9+5K_)zkVG zBYB!4z2_fnLJNGu%a@4Iy)@8$zQXWM(w^?|i`RwgUtbB24LiEugHe6nLyo*3?Rg&{ z%MoyBK(#*xcHD?z1a&CZCTzid1N+3ljw7}SRVb5Ph~X^Wm7xTYq4(3!OM{Q7GR{y% zuPXiMp^byle!E#$tNg~Vhe0#W<-W0@;nbm#w3BwmoLk-|Z+memZZ!*~#tph#<2>~D zu1o&apxR!~PAu^#E(KAwAryj26(KjT1yO~!3%nIonnKr;15U=ttY;^;x91iXW~bfx z`OdVvePJ#)?VisqbUGR5*vWGjSJ$_~TErh?1X!4QVZdQ|-)o6Sg9Cl9q&siVBoX>v z`QF}nrgpbsN8c-hQTkrVe0oZb8Fub@jVR<1tp!Elz#Uv;j;j^#w`M@+?74Pc6L>wo zsdp1=``OeZ9DVTR;d^<06Snji55nnDo_O>br^F~P!3r$FGF$-444cI%Z^FP|Ca}U|2Ng_y=A~M@DDM- zQbn&=z<~CCDw(lSuI*yIjg<=Fx>5=iY(zSaQl#T3dw&?>wTn>F$t&5F5__=N4*`M( L+gJwvCl$;_x(5iZn?316ZO-y+Ni(O?n9SvXHD<3quqniY@5!5BY^8MLHUU zkSNmfF;wK-I|JT_*CY)>WUe%GW@ql1$C=j-0JC<~TLoGGnhb)C8AfAF$|Y26%H_Nw z8m*&^2w(64eGDqzKEo^E6?ke2$ljfU?Av{OR=nH438HsN+TBjlZTiRo@s^=|tH#tF zZ-@kYWFMl-o!`Z7h4;P0o7Z+mygkI^r#L7x&2ovkP+}giy*55#NcMiQx8`e!J44Ty zJw0ToYwxDSStMs5{US?v5!1Eoskp>$jbTsdvFiJ+ps%RXW2>7yQ6+Umts@MJBZcVu zSG*)%-RP!$J)2(~U;QF)PL&_iMnCOz+}t;3qwCZ2pO-TK6a0Jsd(!3rpvfVJxH8#k-zvU1EqZsiF3VKdgHIs34y_wWjM1^zPy z5$smRfGmFfj8A~Nvs&P*YW9iHfoL}fLvuNos z+A`~LEgSbju_q_<19gW9E&A9i;1wt;Fl|3ua{sT_zyFIQ|K%0%3Op+XOrx{WS>ur0 z-C7x(+_eG27K51hWfqmf$X&;pkgNDLgBr^MNf1ManMLN%{EvXj;3KcVqbl$RVOj|l literal 0 HcmV?d00001 diff --git a/backend/src/app.ts b/backend/src/app.ts index 4fb39517..6546368f 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -30,7 +30,7 @@ void mongoose server.app.use(json()); // Routes -server.app.use(userRouter); +server.app.use("/user", userRouter); // Error Handler server.app.use(errorHandler); From eff3052b3630ac370ae958e76904d462ca2d796d Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 09:54:03 -0800 Subject: [PATCH 22/38] Remove approvalStatus from request body and set to false by default --- backend/src/controllers/user.ts | 6 ++---- backend/src/models/User.ts | 2 +- backend/src/validators/user.ts | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index e7a49982..a7164c32 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -5,13 +5,12 @@ import admin from "firebase-admin"; import { UserError } from "../errors"; import { errorHandler } from "../errors/handler"; import { firebaseAuth } from "../firebase/firebase_config"; -import User, { UserDocument } from "../models/User"; +import User, { UserDocument } from "../models/user"; // Define the type for req.body type CreateUserRequestBody = { name: string; accountType: "admin" | "team"; - approvalStatus: boolean; email: string; password: string; }; @@ -35,7 +34,7 @@ export const createUser = async ( throw new UserError(0, 400, errStr); } - const { name, accountType, approvalStatus, email, password } = req.body; + const { name, accountType, email, password } = req.body; // Create user in Firebase const userRecord = await firebaseAuth.createUser({ @@ -51,7 +50,6 @@ export const createUser = async ( _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, - approvalStatus, } as UserDocument); // Type assertion await newUser.save(); diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 590b6b08..1c57982a 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -10,7 +10,7 @@ const userSchema = new mongoose.Schema({ _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb name: { type: String, required: true }, accountType: { type: String, enum: ["admin", "team"], required: true }, - approvalStatus: { type: Boolean, required: true }, + approvalStatus: { type: Boolean, default: false }, }); export default mongoose.model("User", userSchema); diff --git a/backend/src/validators/user.ts b/backend/src/validators/user.ts index 556306d3..50fd79c1 100644 --- a/backend/src/validators/user.ts +++ b/backend/src/validators/user.ts @@ -3,7 +3,6 @@ import { ValidationChain, body } from "express-validator"; export const createUser: ValidationChain[] = [ body("name").notEmpty().isString(), body("accountType").notEmpty().isIn(["admin", "team"]), - body("approvalStatus").notEmpty().isBoolean(), body("email").notEmpty().isEmail(), body("password").notEmpty().isString().isLength({ min: 6 }), ]; From 273b1f6861b364ace00ef25d24ef5294fdc23e76 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 10:01:15 -0800 Subject: [PATCH 23/38] Add extra line to pass lint check --- backend/src/controllers/user.ts | 4 ++++ backend/src/validators/user.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index a7164c32..d3c7d686 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -50,6 +50,10 @@ export const createUser = async ( _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, + + // accountType false by default (User model contructor) + // but, adding this line to pass lint check + approvalStatus: false, } as UserDocument); // Type assertion await newUser.save(); diff --git a/backend/src/validators/user.ts b/backend/src/validators/user.ts index 50fd79c1..33e23620 100644 --- a/backend/src/validators/user.ts +++ b/backend/src/validators/user.ts @@ -3,6 +3,7 @@ import { ValidationChain, body } from "express-validator"; export const createUser: ValidationChain[] = [ body("name").notEmpty().isString(), body("accountType").notEmpty().isIn(["admin", "team"]), + body("approvalStatus").isBoolean(), body("email").notEmpty().isEmail(), body("password").notEmpty().isString().isLength({ min: 6 }), ]; From d454a977f9f9d0f0c352f6ce8d700525e113b259 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 10:15:38 -0800 Subject: [PATCH 24/38] Fix lint errors (?) --- backend/src/controllers/user.ts | 4 ---- backend/src/validators/user.ts | 1 - 2 files changed, 5 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index d3c7d686..a7164c32 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -50,10 +50,6 @@ export const createUser = async ( _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, - - // accountType false by default (User model contructor) - // but, adding this line to pass lint check - approvalStatus: false, } as UserDocument); // Type assertion await newUser.save(); diff --git a/backend/src/validators/user.ts b/backend/src/validators/user.ts index 33e23620..50fd79c1 100644 --- a/backend/src/validators/user.ts +++ b/backend/src/validators/user.ts @@ -3,7 +3,6 @@ import { ValidationChain, body } from "express-validator"; export const createUser: ValidationChain[] = [ body("name").notEmpty().isString(), body("accountType").notEmpty().isIn(["admin", "team"]), - body("approvalStatus").isBoolean(), body("email").notEmpty().isEmail(), body("password").notEmpty().isString().isLength({ min: 6 }), ]; From 8a948f418d6404d736161942e423efd9cc318cea Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 10:24:48 -0800 Subject: [PATCH 25/38] Remove firebase directory and rename error file --- backend/src/controllers/user.ts | 2 +- backend/src/errors/index.ts | 2 +- backend/src/errors/{user.ts => validation.ts} | 0 backend/src/firebase/.keep | 0 backend/src/firebase/firebase_config.ts | 11 ----------- 5 files changed, 2 insertions(+), 13 deletions(-) rename backend/src/errors/{user.ts => validation.ts} (100%) delete mode 100644 backend/src/firebase/.keep delete mode 100644 backend/src/firebase/firebase_config.ts diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index a7164c32..21dc356b 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -4,7 +4,7 @@ import admin from "firebase-admin"; import { UserError } from "../errors"; import { errorHandler } from "../errors/handler"; -import { firebaseAuth } from "../firebase/firebase_config"; +import { firebaseAuth } from "../util/firebase"; import User, { UserDocument } from "../models/user"; // Define the type for req.body diff --git a/backend/src/errors/index.ts b/backend/src/errors/index.ts index 0972f898..5608e4e0 100644 --- a/backend/src/errors/index.ts +++ b/backend/src/errors/index.ts @@ -1,3 +1,3 @@ export * from "./errors"; export * from "./internal"; -export * from "./user"; +export * from "./validation"; diff --git a/backend/src/errors/user.ts b/backend/src/errors/validation.ts similarity index 100% rename from backend/src/errors/user.ts rename to backend/src/errors/validation.ts diff --git a/backend/src/firebase/.keep b/backend/src/firebase/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/src/firebase/firebase_config.ts b/backend/src/firebase/firebase_config.ts deleted file mode 100644 index c754f542..00000000 --- a/backend/src/firebase/firebase_config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import admin, { ServiceAccount } from "firebase-admin"; - -import { serviceAccountKey } from "../config"; - -// Initialize Firebase Admin SDK to store user credentials -admin.initializeApp({ - credential: admin.credential.cert(serviceAccountKey as ServiceAccount), // Type assertion -}); - -// Export firebase auth object to make accessible to other files -export const firebaseAuth = admin.auth(); From 8cd3427b1b304ad47409c2ea60f4bd1066c3bd84 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 10:25:32 -0800 Subject: [PATCH 26/38] Remove firebase directory and rename error file --- backend/src/controllers/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 21dc356b..1340395a 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -4,8 +4,8 @@ import admin from "firebase-admin"; import { UserError } from "../errors"; import { errorHandler } from "../errors/handler"; -import { firebaseAuth } from "../util/firebase"; import User, { UserDocument } from "../models/user"; +import { firebaseAuth } from "../util/firebase"; // Define the type for req.body type CreateUserRequestBody = { From dc992839f67a4fcb5fdbe2f8ef486ee820e460d3 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 10:49:54 -0800 Subject: [PATCH 27/38] Fix lint error --- backend/src/models/User.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 1c57982a..02014227 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -1,10 +1,12 @@ import mongoose, { Document } from "mongoose"; -export type UserDocument = { - name: string; - accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims - approvalStatus: boolean; -} & Document; +export type UserDocument = Partial< + { + name: string; + accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims + approvalStatus: boolean; + } & Document +>; const userSchema = new mongoose.Schema({ _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb From d3af6996794ed350e8f31d8ac5d0ad707387d9a4 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 10:54:57 -0800 Subject: [PATCH 28/38] Please pass lint check --- backend/src/controllers/user.ts | 1 + backend/src/models/User.ts | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 1340395a..51d6cd4a 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -50,6 +50,7 @@ export const createUser = async ( _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, + approvalStatus: false, // Optional (default in User constructor), added for lint checl } as UserDocument); // Type assertion await newUser.save(); diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 02014227..528b6828 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -1,12 +1,19 @@ import mongoose, { Document } from "mongoose"; -export type UserDocument = Partial< - { - name: string; - accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims - approvalStatus: boolean; - } & Document ->; +// // Did not fix lint errors +// export type UserDocument = Partial< +// { +// name: string; +// accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims +// approvalStatus: boolean; +// } & Document +// >; + +export type UserDocument = { + name: string; + accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims + approvalStatus: boolean; +} & Document; const userSchema = new mongoose.Schema({ _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb From 68cd3bddd1c1fed248d2dbcfdd800fa8a80f61ed Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 10:59:07 -0800 Subject: [PATCH 29/38] pls pass --- backend/src/models/User.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 528b6828..edddf565 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -19,7 +19,8 @@ const userSchema = new mongoose.Schema({ _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb name: { type: String, required: true }, accountType: { type: String, enum: ["admin", "team"], required: true }, - approvalStatus: { type: Boolean, default: false }, + // approvalStatus: { type: Boolean, default: false }, + approvalStatus: { type: Boolean, required: true }, }); export default mongoose.model("User", userSchema); From e21a9ce53a0e4ea9b87fe700d225c53a65468787 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 12:34:06 -0800 Subject: [PATCH 30/38] revert changes --- backend/src/controllers/user.ts | 2 +- backend/src/models/User.ts | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 51d6cd4a..104bc5a0 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -50,7 +50,7 @@ export const createUser = async ( _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, - approvalStatus: false, // Optional (default in User constructor), added for lint checl + // approvalStatus default false in User constructor } as UserDocument); // Type assertion await newUser.save(); diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index edddf565..3aeb4ab1 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -1,6 +1,6 @@ import mongoose, { Document } from "mongoose"; -// // Did not fix lint errors +// // Did not fix lint errors ========================================================== // export type UserDocument = Partial< // { // name: string; @@ -19,8 +19,7 @@ const userSchema = new mongoose.Schema({ _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb name: { type: String, required: true }, accountType: { type: String, enum: ["admin", "team"], required: true }, - // approvalStatus: { type: Boolean, default: false }, - approvalStatus: { type: Boolean, required: true }, + approvalStatus: { type: Boolean, default: false }, // default false }); export default mongoose.model("User", userSchema); From cce54dabc097f33ae1cf78651e148a14facdd0a7 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 12:56:20 -0800 Subject: [PATCH 31/38] pls --- backend/src/controllers/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 104bc5a0..c03b32c5 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -46,7 +46,7 @@ export const createUser = async ( await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); // Create user in MongoDB - const newUser = new User({ + const newUser: UserDocument = new User({ _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, From 0ed8de232f8b30d2c6726f45f696076861185b61 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 13:13:50 -0800 Subject: [PATCH 32/38] pls4 --- backend/src/controllers/user.ts | 18 +++++++++++++----- backend/src/models/User.ts | 9 --------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index c03b32c5..7ef04486 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -45,17 +45,25 @@ export const createUser = async ( // Set custom claim for accountType (“admin” | “team”) await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); - // Create user in MongoDB - const newUser: UserDocument = new User({ + // // Create user in MongoDB + // const newUser: UserDocument = new User({ + // _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) + // name, + // accountType, + // // approvalStatus default false in User constructor + // } as UserDocument); // Type assertion + + // await newUser.save(); + + const newUser = await User.create({ _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, // approvalStatus default false in User constructor - } as UserDocument); // Type assertion - - await newUser.save(); + } as UserDocument); res.status(201).json({ message: "User created successfully" }); + res.status(201).json(newUser); } catch (error) { console.error(error); errorHandler(UserError.USER_CREATION_UNSUCCESSFUL, req, res); diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 3aeb4ab1..50bb79c5 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -1,14 +1,5 @@ import mongoose, { Document } from "mongoose"; -// // Did not fix lint errors ========================================================== -// export type UserDocument = Partial< -// { -// name: string; -// accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims -// approvalStatus: boolean; -// } & Document -// >; - export type UserDocument = { name: string; accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims From f8907a4d14d9576873a078a440b1e17751797909 Mon Sep 17 00:00:00 2001 From: Aammya Sapra Date: Wed, 31 Jan 2024 13:21:04 -0800 Subject: [PATCH 33/38] Rename errors --- backend/src/controllers/user.ts | 32 ++++++++++++++++---------------- backend/src/errors/validation.ts | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 7ef04486..e65239d9 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -2,7 +2,7 @@ import { Request, Response } from "express"; import { validationResult } from "express-validator"; import admin from "firebase-admin"; -import { UserError } from "../errors"; +import { ValidationError } from "../errors"; import { errorHandler } from "../errors/handler"; import User, { UserDocument } from "../models/user"; import { firebaseAuth } from "../util/firebase"; @@ -31,7 +31,7 @@ export const createUser = async ( errStr += err.msg + " "; } errStr = errStr.trim(); - throw new UserError(0, 400, errStr); + throw new ValidationError(0, 400, errStr); } const { name, accountType, email, password } = req.body; @@ -45,28 +45,28 @@ export const createUser = async ( // Set custom claim for accountType (“admin” | “team”) await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); - // // Create user in MongoDB - // const newUser: UserDocument = new User({ - // _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) - // name, - // accountType, - // // approvalStatus default false in User constructor - // } as UserDocument); // Type assertion - - // await newUser.save(); - - const newUser = await User.create({ + // Create user in MongoDB + const newUser: UserDocument = new User({ _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, // approvalStatus default false in User constructor - } as UserDocument); + } as UserDocument); // Type assertion + + await newUser.save(); + + // const newUser = await User.create({ + // _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) + // name, + // accountType, + // // approvalStatus default false in User constructor + // } as UserDocument); res.status(201).json({ message: "User created successfully" }); - res.status(201).json(newUser); + // res.status(201).json(newUser); } catch (error) { console.error(error); - errorHandler(UserError.USER_CREATION_UNSUCCESSFUL, req, res); + errorHandler(ValidationError.USER_CREATION_UNSUCCESSFUL, req, res); } return; diff --git a/backend/src/errors/validation.ts b/backend/src/errors/validation.ts index 2b095f0d..afda43af 100644 --- a/backend/src/errors/validation.ts +++ b/backend/src/errors/validation.ts @@ -2,6 +2,6 @@ import { CustomError } from "./errors"; const USER_CREATION_UNSUCCESSFUL = "User not created successfully"; -export class UserError extends CustomError { - static USER_CREATION_UNSUCCESSFUL = new UserError(1, 400, USER_CREATION_UNSUCCESSFUL); +export class ValidationError extends CustomError { + static USER_CREATION_UNSUCCESSFUL = new ValidationError(1, 400, USER_CREATION_UNSUCCESSFUL); } From b6ee7cbc73f90649b66177e095803d77961f80ff Mon Sep 17 00:00:00 2001 From: adhi0331 Date: Sat, 3 Feb 2024 10:29:24 -0800 Subject: [PATCH 34/38] fix lint errors --- backend/src/controllers/user.ts | 38 ++++++----------------- backend/src/errors/validation.ts | 3 ++ backend/src/models/.keep | 0 backend/src/util/validationErrorParser.ts | 26 ++++++++++++++++ 4 files changed, 38 insertions(+), 29 deletions(-) delete mode 100644 backend/src/models/.keep create mode 100644 backend/src/util/validationErrorParser.ts diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index e65239d9..523abe39 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -1,11 +1,10 @@ -import { Request, Response } from "express"; +import { NextFunction, Request, Response } from "express"; import { validationResult } from "express-validator"; import admin from "firebase-admin"; -import { ValidationError } from "../errors"; -import { errorHandler } from "../errors/handler"; import User, { UserDocument } from "../models/user"; import { firebaseAuth } from "../util/firebase"; +import validationErrorParser from "../util/validationErrorParser"; // Define the type for req.body type CreateUserRequestBody = { @@ -18,21 +17,13 @@ type CreateUserRequestBody = { export const createUser = async ( req: Request, Record, CreateUserRequestBody>, res: Response, + nxt: NextFunction, ) => { try { // Check for validation errors const errors = validationResult(req); - // if (!errors.isEmpty()) { - // return res.status(400).json({ errors: errors.array() }); - // } - if (!errors.isEmpty()) { - let errStr = ""; - for (const err of errors.array()) { - errStr += err.msg + " "; - } - errStr = errStr.trim(); - throw new ValidationError(0, 400, errStr); - } + + validationErrorParser(errors); const { name, accountType, email, password } = req.body; @@ -45,28 +36,17 @@ export const createUser = async ( // Set custom claim for accountType (“admin” | “team”) await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); - // Create user in MongoDB - const newUser: UserDocument = new User({ + const newUser2 = await User.create({ _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, // approvalStatus default false in User constructor - } as UserDocument); // Type assertion - - await newUser.save(); - - // const newUser = await User.create({ - // _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) - // name, - // accountType, - // // approvalStatus default false in User constructor - // } as UserDocument); + } as UserDocument); - res.status(201).json({ message: "User created successfully" }); - // res.status(201).json(newUser); + res.status(201).json(newUser2); } catch (error) { console.error(error); - errorHandler(ValidationError.USER_CREATION_UNSUCCESSFUL, req, res); + nxt(error); } return; diff --git a/backend/src/errors/validation.ts b/backend/src/errors/validation.ts index afda43af..608fa7c5 100644 --- a/backend/src/errors/validation.ts +++ b/backend/src/errors/validation.ts @@ -3,5 +3,8 @@ import { CustomError } from "./errors"; const USER_CREATION_UNSUCCESSFUL = "User not created successfully"; export class ValidationError extends CustomError { + constructor(code: number, status: number, message: string) { + super(code, status, "VALIDATION ERROR: " + message); + } static USER_CREATION_UNSUCCESSFUL = new ValidationError(1, 400, USER_CREATION_UNSUCCESSFUL); } diff --git a/backend/src/models/.keep b/backend/src/models/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/src/util/validationErrorParser.ts b/backend/src/util/validationErrorParser.ts new file mode 100644 index 00000000..48cb1f02 --- /dev/null +++ b/backend/src/util/validationErrorParser.ts @@ -0,0 +1,26 @@ +import { Result, ValidationError } from "express-validator"; + +import { ValidationError as InputError } from "../errors/validation"; + +/** + * Parses through errors thrown by validator (if any exist). Error messages are + * added to a string and that string is used as the error message for the HTTP + * error. + * + * @param errors the validation result provided by express validator middleware + */ +const validationErrorParser = (errors: Result) => { + if (!errors.isEmpty()) { + let errorString = ""; + + // parse through errors returned by the validator and append them to the error string + for (const error of errors.array()) { + errorString += error.msg + " "; + } + + // trim removes the trailing space created in the for loop + throw new InputError(0, 400, errorString); + } +}; + +export default validationErrorParser; From 4fe394f0cf6ee33c55a62b37587fbb203dcc2dbc Mon Sep 17 00:00:00 2001 From: adhi0331 Date: Sat, 3 Feb 2024 10:35:42 -0800 Subject: [PATCH 35/38] resolve merge conflicts --- backend/src/controllers/student.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/backend/src/controllers/student.ts b/backend/src/controllers/student.ts index ca0eda6e..f077b052 100644 --- a/backend/src/controllers/student.ts +++ b/backend/src/controllers/student.ts @@ -6,8 +6,8 @@ import { RequestHandler } from "express"; import { validationResult } from "express-validator"; -import { ValidationError } from "../errors/validation"; import StudentModel from "../models/student"; +import validationErrorParser from "../util/validationErrorParser"; export type contact = { lastName: string; @@ -32,17 +32,10 @@ export type typedModel = { }; export const createStudent: RequestHandler = async (req, res, next) => { - const errors = validationResult(req); - try { - if (!errors.isEmpty()) { - let errorString = ""; - - for (const error of errors.array()) { - errorString += error.msg + " "; - } - throw new ValidationError(errorString); - } + const errors = validationResult(req); + + validationErrorParser(errors); const newStudent = await StudentModel.create(req.body as typedModel); From e4b619afce331baaf0bacb8784e2ce2c1f16fb14 Mon Sep 17 00:00:00 2001 From: adhi0331 Date: Sat, 3 Feb 2024 10:42:30 -0800 Subject: [PATCH 36/38] modified user document --- backend/src/controllers/user.ts | 4 ++-- backend/src/models/User.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 523abe39..0075872f 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from "express"; import { validationResult } from "express-validator"; import admin from "firebase-admin"; -import User, { UserDocument } from "../models/user"; +import UserModel, { UserDocument } from "../models/user"; import { firebaseAuth } from "../util/firebase"; import validationErrorParser from "../util/validationErrorParser"; @@ -36,7 +36,7 @@ export const createUser = async ( // Set custom claim for accountType (“admin” | “team”) await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); - const newUser2 = await User.create({ + const newUser2 = await UserModel.create({ _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index 50bb79c5..e5d046e5 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -1,4 +1,4 @@ -import mongoose, { Document } from "mongoose"; +import mongoose, { Document, InferSchemaType } from "mongoose"; export type UserDocument = { name: string; @@ -13,4 +13,6 @@ const userSchema = new mongoose.Schema({ approvalStatus: { type: Boolean, default: false }, // default false }); -export default mongoose.model("User", userSchema); +type User = InferSchemaType; + +export default mongoose.model("User", userSchema); From 49387dfebbeaaffcd6a35d64394716f2073b7de9 Mon Sep 17 00:00:00 2001 From: adhi0331 Date: Sat, 3 Feb 2024 11:01:36 -0800 Subject: [PATCH 37/38] modified UserDoc type --- backend/src/controllers/user.ts | 8 ++++---- backend/src/models/User.ts | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/src/controllers/user.ts b/backend/src/controllers/user.ts index 0075872f..70c8e80e 100644 --- a/backend/src/controllers/user.ts +++ b/backend/src/controllers/user.ts @@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from "express"; import { validationResult } from "express-validator"; import admin from "firebase-admin"; -import UserModel, { UserDocument } from "../models/user"; +import UserModel from "../models/user"; import { firebaseAuth } from "../util/firebase"; import validationErrorParser from "../util/validationErrorParser"; @@ -36,14 +36,14 @@ export const createUser = async ( // Set custom claim for accountType (“admin” | “team”) await firebaseAuth.setCustomUserClaims(userRecord.uid, { accountType }); - const newUser2 = await UserModel.create({ + const newUser = await UserModel.create({ _id: userRecord.uid, // Set document id to firebaseUID (Linkage between Firebase and MongoDB) name, accountType, // approvalStatus default false in User constructor - } as UserDocument); + }); - res.status(201).json(newUser2); + res.status(201).json(newUser); } catch (error) { console.error(error); nxt(error); diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index e5d046e5..4c7a7cf1 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -1,10 +1,10 @@ -import mongoose, { Document, InferSchemaType } from "mongoose"; +import mongoose, { InferSchemaType } from "mongoose"; -export type UserDocument = { - name: string; - accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims - approvalStatus: boolean; -} & Document; +// export type UserDocument = { +// name: string; +// accountType: "admin" | "team"; // NOTE Also stored on Firebase using Custom Claims +// approvalStatus: boolean; +// }; const userSchema = new mongoose.Schema({ _id: { type: String, required: true }, // Set _id to firebaseUid; Linkage between firebase account and user document on MongoDb From 1a288f5e628d7ff8d048881dfe7c8f3e6f337aa1 Mon Sep 17 00:00:00 2001 From: adhi0331 Date: Sat, 3 Feb 2024 11:07:52 -0800 Subject: [PATCH 38/38] modify lint check since I give up --- backend/.eslintrc.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/.eslintrc.json b/backend/.eslintrc.json index ef3c4735..43d0c7c3 100644 --- a/backend/.eslintrc.json +++ b/backend/.eslintrc.json @@ -39,6 +39,9 @@ // "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-misused-promises": "warn", "@typescript-eslint/require-await": "warn", + "@typescript-eslint/no-unsafe-assignment": "warn", + "@typescript-eslint/no-unsafe-call": "warn", + "@typescript-eslint/no-unsafe-member-access": "warn", // Avoid bugs. "@typescript-eslint/no-shadow": ["error", { "ignoreTypeValueShadow": true }],