From 6ca5cf869cd94180e70924253354a4c8272846be Mon Sep 17 00:00:00 2001 From: janetxinli Date: Fri, 6 Aug 2021 16:13:28 -0700 Subject: [PATCH 1/6] Configure firebase --- client/.gitignore | 1 + client/package-lock.json | 1100 ++++++++++++++++++++++++++++++++++++++ client/package.json | 1 + client/src/firebase.ts | 13 + 4 files changed, 1115 insertions(+) create mode 100644 client/src/firebase.ts diff --git a/client/.gitignore b/client/.gitignore index cdcaf39..7ac0e08 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -21,3 +21,4 @@ yarn.lock npm-debug.log* yarn-debug.log* yarn-error.log* +.env* \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index d1bed7b..fb9e766 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -21,6 +21,7 @@ "@types/react-table": "^7.7.1", "axios": "^0.21.1", "d3": "^6.7.0", + "firebase": "^8.8.1", "match-sorter": "^6.3.0", "qs": "^6.10.1", "react": "^17.0.2", @@ -1947,6 +1948,447 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@firebase/analytics": { + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.6.16.tgz", + "integrity": "sha512-eBYWKf7S7xmDFi3cWLs7Z6x4Hn1AG1oy2Xp/RvfyamhqI2X8GbgyCif/+q7orh+MWnNwipblVT93YajhhXpQcQ==", + "dependencies": { + "@firebase/analytics-types": "0.5.0", + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/analytics-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.5.0.tgz", + "integrity": "sha512-VTV5Xtq5gVabbL/4n6pBtMJWcQBgOUDE2XbEHl8EOuwRaU9weyGUS7ofbisDkpl1RlFU1aewnc33pbLcYbi0iQ==" + }, + "node_modules/@firebase/app": { + "version": "0.6.29", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.29.tgz", + "integrity": "sha512-duCzk9/BSVVsb5Y9b0rnvGSuD5zQA/JghiQsccRl+lA4xiUYjFudTU4cVFftkw+0zzeYBHn4KiVxchsva1O9dA==", + "dependencies": { + "@firebase/app-types": "0.6.3", + "@firebase/component": "0.5.5", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "dom-storage": "2.1.0", + "tslib": "^2.1.0", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/@firebase/app-check": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.2.1.tgz", + "integrity": "sha512-Qswn+qHiAyi3P0O/W9BffDFX4MmptSod49zhWQt8vV42JyKSZexaXQpeNlfKgdE5jX8wUw8Vkk8My4PfIrPkww==", + "dependencies": { + "@firebase/app-check-interop-types": "0.1.0", + "@firebase/app-check-types": "0.2.0", + "@firebase/component": "0.5.5", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.0.tgz", + "integrity": "sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.2.0.tgz", + "integrity": "sha512-CfZhWtChLK9uNmrxbJyTg1BPtROiwc/VJGu3f39KjS0F5ZvZjHmyRFMrDiSoXDoybM4B6X0pQhJYi9rifT2wpQ==" + }, + "node_modules/@firebase/app-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.3.tgz", + "integrity": "sha512-/M13DPPati7FQHEQ9Minjk1HGLm/4K4gs9bR4rzLCWJg64yGtVC0zNg9gDpkw9yc2cvol/mNFxqTtd4geGrwdw==" + }, + "node_modules/@firebase/auth": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.16.8.tgz", + "integrity": "sha512-mR0UXG4LirWIfOiCWxVmvz1o23BuKGxeItQ2cCUgXLTjNtWJXdcky/356iTUsd7ZV5A78s2NHeN5tIDDG6H4rg==", + "dependencies": { + "@firebase/auth-types": "0.10.3" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", + "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/auth-types": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.3.tgz", + "integrity": "sha512-zExrThRqyqGUbXOFrH/sowuh2rRtfKHp9SBVY2vOqKWdCX1Ztn682n9WLtlUDsiYVIbBcwautYWk2HyCGFv0OA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.5.tgz", + "integrity": "sha512-L41SdS/4a164jx2iGfakJgaBUPPBI3DI+RrUlmh3oHSUljTeCwfj/Nhcv3S7e2lyXsGFJtAyepfPUx4IQ05crw==", + "dependencies": { + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "0.10.9", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.10.9.tgz", + "integrity": "sha512-Jxi9SiE4cNOftO9YKlG71ccyWFw4kSM9AG/xYu6vWXUGBr39Uw1TvYougANOcU21Q0TP4J08VPGnOnpXk/FGbQ==", + "dependencies": { + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.5", + "@firebase/database-types": "0.7.3", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "faye-websocket": "0.11.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.7.3.tgz", + "integrity": "sha512-dSOJmhKQ0nL8O4EQMRNGpSExWCXeHtH57gGg0BfNAdWcKhC8/4Y+qfKLfWXzyHvrSecpLmO0SmAi/iK2D5fp5A==", + "dependencies": { + "@firebase/app-types": "0.6.3" + } + }, + "node_modules/@firebase/database/node_modules/faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@firebase/firestore": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.3.10.tgz", + "integrity": "sha512-O+XpaZVhDIBK2fMwBUBR2BuhaXF6zTmz+afAuXAx18DK+2rFfLefbALZLaUYw0Aabe9pryy0c7OenzRbHA8n4Q==", + "dependencies": { + "@firebase/component": "0.5.5", + "@firebase/firestore-types": "2.3.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "@firebase/webchannel-wrapper": "0.5.1", + "@grpc/grpc-js": "^1.3.2", + "@grpc/proto-loader": "^0.6.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.3.0.tgz", + "integrity": "sha512-QTW7NP7nDL0pgT/X53lyj+mIMh4nRQBBTBlRNQBt7eSyeqBf3ag3bxdQhCg358+5KbjYTC2/O6QtX9DlJZmh1A==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/functions": { + "version": "0.6.14", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.6.14.tgz", + "integrity": "sha512-Gthru/wHPQqkn651MenVM+qKVFFqIyFcNT3qfJUacibqrKlvDtYtaCMjFGAkChuGnYzNVnXJIaNrIHkEIII4Hg==", + "dependencies": { + "@firebase/component": "0.5.5", + "@firebase/functions-types": "0.4.0", + "@firebase/messaging-types": "0.5.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.4.0.tgz", + "integrity": "sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ==" + }, + "node_modules/@firebase/installations": { + "version": "0.4.31", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.31.tgz", + "integrity": "sha512-qWolhAgMHvD3avsNCl+K8+untzoDDFQIRR8At8kyWMKKosy0vttdWTWzjvDoZbyKU6r0RNlxDUWAgV88Q8EudQ==", + "dependencies": { + "@firebase/component": "0.5.5", + "@firebase/installations-types": "0.3.4", + "@firebase/util": "1.2.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz", + "integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "node_modules/@firebase/messaging": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.7.15.tgz", + "integrity": "sha512-81t6iJtqMBJF5LHTjDhlHUpbPZOV6dKhW0TueAoON4omc0SaDXgf4nnk6JkvZRfdcuOaP8848Cv53tvZPFFAYQ==", + "dependencies": { + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/messaging-types": "0.5.0", + "@firebase/util": "1.2.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/messaging-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.5.0.tgz", + "integrity": "sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/performance": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.17.tgz", + "integrity": "sha512-uhDs9rhdMrGraYHcd3CTRkGtcNap4hp6rAHTwJNIX56Z3RzQ1VW2ea9vvesl7EjFtEIPU0jfdrS32wV+qer5DQ==", + "dependencies": { + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/logger": "0.2.6", + "@firebase/performance-types": "0.0.13", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/performance-types": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.13.tgz", + "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA==" + }, + "node_modules/@firebase/polyfill": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.36.tgz", + "integrity": "sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg==", + "dependencies": { + "core-js": "3.6.5", + "promise-polyfill": "8.1.3", + "whatwg-fetch": "2.0.4" + } + }, + "node_modules/@firebase/polyfill/node_modules/core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/@firebase/polyfill/node_modules/whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + }, + "node_modules/@firebase/remote-config": { + "version": "0.1.42", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.42.tgz", + "integrity": "sha512-hWwtAZmYLB274bxjV2cdMYhyBCUUqbYErihGx3rMyab76D+VbIxOuKJb2z0DS67jQG+SA3pr9/MtWsTPHV/l9g==", + "dependencies": { + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/logger": "0.2.6", + "@firebase/remote-config-types": "0.1.9", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz", + "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==" + }, + "node_modules/@firebase/storage": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.6.1.tgz", + "integrity": "sha512-00WEdmmKoKUHBsufUIUDgBS5ghAe8tCp1QbHQnnlf3aekAgFf8UKjfR6QMaHoEIzuZPhWPStQ5KrrIcWA/MMQg==", + "dependencies": { + "@firebase/component": "0.5.5", + "@firebase/storage-types": "0.4.1", + "@firebase/util": "1.2.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.4.1.tgz", + "integrity": "sha512-IM4cRzAnQ6QZoaxVZ5MatBzqXVcp47hOlE28jd9xXw1M9V7gfjhmW0PALGFQx58tPVmuUwIKyoEbHZjV4qRJwQ==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/util": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.2.0.tgz", + "integrity": "sha512-8W9TTGImXr9cu+oyjBJ7yjoEd/IVAv0pBZA4c1uIuKrpGZi2ee38m+8xlZOBRmsAaOU/tR9DXz1WF/oeM6Fb7Q==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.5.1.tgz", + "integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A==" + }, + "node_modules/@grpc/grpc-js": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.6.tgz", + "integrity": "sha512-v7+LQFbqZKmd/Tvf5/j1Xlbq6jXL/4d+gUtm2TNX4QiEC3ELWADmGr2dGlUyLl6aKTuYfsN72vAsO5zmavYkEg==", + "dependencies": { + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.4.tgz", + "integrity": "sha512-7xvDvW/vJEcmLUltCUGOgWRPM8Oofv0eCFSVMuKqaqWJaXSzmB+m9hiyqe34QofAl4WAzIKUZZlinIF9FOHyTQ==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.10.0", + "yargs": "^16.1.1" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@grpc/proto-loader/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==", + "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/@grpc/proto-loader/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -2673,6 +3115,60 @@ "node": ">= 8" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "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==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "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": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, "node_modules/@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -3484,6 +3980,11 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==" }, + "node_modules/@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, "node_modules/@types/match-sorter": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@types/match-sorter/-/match-sorter-6.0.0.tgz", @@ -7446,6 +7947,14 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-storage": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", + "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==", + "engines": { + "node": "*" + } + }, "node_modules/domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -9327,6 +9836,31 @@ "node": ">=8" } }, + "node_modules/firebase": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.8.1.tgz", + "integrity": "sha512-dzqQn3wwHhsStsD2gDs3XfSJ/SIqv5IA9Ht+MySnvrIsljk0V8bI/+EMPsh0h2VlYPSk51bmyNQZ4LvuSKNvlA==", + "dependencies": { + "@firebase/analytics": "0.6.16", + "@firebase/app": "0.6.29", + "@firebase/app-check": "0.2.1", + "@firebase/app-types": "0.6.3", + "@firebase/auth": "0.16.8", + "@firebase/database": "0.10.9", + "@firebase/firestore": "2.3.10", + "@firebase/functions": "0.6.14", + "@firebase/installations": "0.4.31", + "@firebase/messaging": "0.7.15", + "@firebase/performance": "0.4.17", + "@firebase/polyfill": "0.3.36", + "@firebase/remote-config": "0.1.42", + "@firebase/storage": "0.6.1", + "@firebase/util": "1.2.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -10490,6 +11024,11 @@ "node": ">= 6" } }, + "node_modules/idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, "node_modules/identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", @@ -13054,6 +13593,11 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -13113,6 +13657,11 @@ "url": "https://tidelift.com/funding/github/npm/loglevel" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -13678,6 +14227,14 @@ "tslib": "^2.0.3" } }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, "node_modules/node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -16035,6 +16592,11 @@ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" }, + "node_modules/promise-polyfill": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", + "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" + }, "node_modules/prompts": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", @@ -16062,6 +16624,36 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "hasInstallScript": 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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/protobufjs/node_modules/@types/node": { + "version": "16.4.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.12.tgz", + "integrity": "sha512-zxrTNFl9Z8boMJXs6ieqZP0wAhvkdzmHSxTlJabM16cf5G9xBc1uPRH5Bbv2omEDDiM8MzTfqTJXBf0Ba4xFWA==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -21803,6 +22395,14 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -23175,6 +23775,363 @@ } } }, + "@firebase/analytics": { + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.6.16.tgz", + "integrity": "sha512-eBYWKf7S7xmDFi3cWLs7Z6x4Hn1AG1oy2Xp/RvfyamhqI2X8GbgyCif/+q7orh+MWnNwipblVT93YajhhXpQcQ==", + "requires": { + "@firebase/analytics-types": "0.5.0", + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + } + }, + "@firebase/analytics-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.5.0.tgz", + "integrity": "sha512-VTV5Xtq5gVabbL/4n6pBtMJWcQBgOUDE2XbEHl8EOuwRaU9weyGUS7ofbisDkpl1RlFU1aewnc33pbLcYbi0iQ==" + }, + "@firebase/app": { + "version": "0.6.29", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.29.tgz", + "integrity": "sha512-duCzk9/BSVVsb5Y9b0rnvGSuD5zQA/JghiQsccRl+lA4xiUYjFudTU4cVFftkw+0zzeYBHn4KiVxchsva1O9dA==", + "requires": { + "@firebase/app-types": "0.6.3", + "@firebase/component": "0.5.5", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "dom-storage": "2.1.0", + "tslib": "^2.1.0", + "xmlhttprequest": "1.8.0" + } + }, + "@firebase/app-check": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.2.1.tgz", + "integrity": "sha512-Qswn+qHiAyi3P0O/W9BffDFX4MmptSod49zhWQt8vV42JyKSZexaXQpeNlfKgdE5jX8wUw8Vkk8My4PfIrPkww==", + "requires": { + "@firebase/app-check-interop-types": "0.1.0", + "@firebase/app-check-types": "0.2.0", + "@firebase/component": "0.5.5", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + } + }, + "@firebase/app-check-interop-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.0.tgz", + "integrity": "sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==" + }, + "@firebase/app-check-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.2.0.tgz", + "integrity": "sha512-CfZhWtChLK9uNmrxbJyTg1BPtROiwc/VJGu3f39KjS0F5ZvZjHmyRFMrDiSoXDoybM4B6X0pQhJYi9rifT2wpQ==" + }, + "@firebase/app-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.3.tgz", + "integrity": "sha512-/M13DPPati7FQHEQ9Minjk1HGLm/4K4gs9bR4rzLCWJg64yGtVC0zNg9gDpkw9yc2cvol/mNFxqTtd4geGrwdw==" + }, + "@firebase/auth": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.16.8.tgz", + "integrity": "sha512-mR0UXG4LirWIfOiCWxVmvz1o23BuKGxeItQ2cCUgXLTjNtWJXdcky/356iTUsd7ZV5A78s2NHeN5tIDDG6H4rg==", + "requires": { + "@firebase/auth-types": "0.10.3" + } + }, + "@firebase/auth-interop-types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", + "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==", + "requires": {} + }, + "@firebase/auth-types": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.3.tgz", + "integrity": "sha512-zExrThRqyqGUbXOFrH/sowuh2rRtfKHp9SBVY2vOqKWdCX1Ztn682n9WLtlUDsiYVIbBcwautYWk2HyCGFv0OA==", + "requires": {} + }, + "@firebase/component": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.5.tgz", + "integrity": "sha512-L41SdS/4a164jx2iGfakJgaBUPPBI3DI+RrUlmh3oHSUljTeCwfj/Nhcv3S7e2lyXsGFJtAyepfPUx4IQ05crw==", + "requires": { + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + } + }, + "@firebase/database": { + "version": "0.10.9", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.10.9.tgz", + "integrity": "sha512-Jxi9SiE4cNOftO9YKlG71ccyWFw4kSM9AG/xYu6vWXUGBr39Uw1TvYougANOcU21Q0TP4J08VPGnOnpXk/FGbQ==", + "requires": { + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.5", + "@firebase/database-types": "0.7.3", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "faye-websocket": "0.11.3", + "tslib": "^2.1.0" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "@firebase/database-types": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.7.3.tgz", + "integrity": "sha512-dSOJmhKQ0nL8O4EQMRNGpSExWCXeHtH57gGg0BfNAdWcKhC8/4Y+qfKLfWXzyHvrSecpLmO0SmAi/iK2D5fp5A==", + "requires": { + "@firebase/app-types": "0.6.3" + } + }, + "@firebase/firestore": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.3.10.tgz", + "integrity": "sha512-O+XpaZVhDIBK2fMwBUBR2BuhaXF6zTmz+afAuXAx18DK+2rFfLefbALZLaUYw0Aabe9pryy0c7OenzRbHA8n4Q==", + "requires": { + "@firebase/component": "0.5.5", + "@firebase/firestore-types": "2.3.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.2.0", + "@firebase/webchannel-wrapper": "0.5.1", + "@grpc/grpc-js": "^1.3.2", + "@grpc/proto-loader": "^0.6.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + } + }, + "@firebase/firestore-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.3.0.tgz", + "integrity": "sha512-QTW7NP7nDL0pgT/X53lyj+mIMh4nRQBBTBlRNQBt7eSyeqBf3ag3bxdQhCg358+5KbjYTC2/O6QtX9DlJZmh1A==", + "requires": {} + }, + "@firebase/functions": { + "version": "0.6.14", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.6.14.tgz", + "integrity": "sha512-Gthru/wHPQqkn651MenVM+qKVFFqIyFcNT3qfJUacibqrKlvDtYtaCMjFGAkChuGnYzNVnXJIaNrIHkEIII4Hg==", + "requires": { + "@firebase/component": "0.5.5", + "@firebase/functions-types": "0.4.0", + "@firebase/messaging-types": "0.5.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + } + }, + "@firebase/functions-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.4.0.tgz", + "integrity": "sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ==" + }, + "@firebase/installations": { + "version": "0.4.31", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.31.tgz", + "integrity": "sha512-qWolhAgMHvD3avsNCl+K8+untzoDDFQIRR8At8kyWMKKosy0vttdWTWzjvDoZbyKU6r0RNlxDUWAgV88Q8EudQ==", + "requires": { + "@firebase/component": "0.5.5", + "@firebase/installations-types": "0.3.4", + "@firebase/util": "1.2.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + } + }, + "@firebase/installations-types": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz", + "integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q==", + "requires": {} + }, + "@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "@firebase/messaging": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.7.15.tgz", + "integrity": "sha512-81t6iJtqMBJF5LHTjDhlHUpbPZOV6dKhW0TueAoON4omc0SaDXgf4nnk6JkvZRfdcuOaP8848Cv53tvZPFFAYQ==", + "requires": { + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/messaging-types": "0.5.0", + "@firebase/util": "1.2.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + } + }, + "@firebase/messaging-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.5.0.tgz", + "integrity": "sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg==", + "requires": {} + }, + "@firebase/performance": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.17.tgz", + "integrity": "sha512-uhDs9rhdMrGraYHcd3CTRkGtcNap4hp6rAHTwJNIX56Z3RzQ1VW2ea9vvesl7EjFtEIPU0jfdrS32wV+qer5DQ==", + "requires": { + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/logger": "0.2.6", + "@firebase/performance-types": "0.0.13", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + } + }, + "@firebase/performance-types": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.13.tgz", + "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA==" + }, + "@firebase/polyfill": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.36.tgz", + "integrity": "sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg==", + "requires": { + "core-js": "3.6.5", + "promise-polyfill": "8.1.3", + "whatwg-fetch": "2.0.4" + }, + "dependencies": { + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + }, + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + } + } + }, + "@firebase/remote-config": { + "version": "0.1.42", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.42.tgz", + "integrity": "sha512-hWwtAZmYLB274bxjV2cdMYhyBCUUqbYErihGx3rMyab76D+VbIxOuKJb2z0DS67jQG+SA3pr9/MtWsTPHV/l9g==", + "requires": { + "@firebase/component": "0.5.5", + "@firebase/installations": "0.4.31", + "@firebase/logger": "0.2.6", + "@firebase/remote-config-types": "0.1.9", + "@firebase/util": "1.2.0", + "tslib": "^2.1.0" + } + }, + "@firebase/remote-config-types": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz", + "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==" + }, + "@firebase/storage": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.6.1.tgz", + "integrity": "sha512-00WEdmmKoKUHBsufUIUDgBS5ghAe8tCp1QbHQnnlf3aekAgFf8UKjfR6QMaHoEIzuZPhWPStQ5KrrIcWA/MMQg==", + "requires": { + "@firebase/component": "0.5.5", + "@firebase/storage-types": "0.4.1", + "@firebase/util": "1.2.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + } + }, + "@firebase/storage-types": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.4.1.tgz", + "integrity": "sha512-IM4cRzAnQ6QZoaxVZ5MatBzqXVcp47hOlE28jd9xXw1M9V7gfjhmW0PALGFQx58tPVmuUwIKyoEbHZjV4qRJwQ==", + "requires": {} + }, + "@firebase/util": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.2.0.tgz", + "integrity": "sha512-8W9TTGImXr9cu+oyjBJ7yjoEd/IVAv0pBZA4c1uIuKrpGZi2ee38m+8xlZOBRmsAaOU/tR9DXz1WF/oeM6Fb7Q==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@firebase/webchannel-wrapper": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.5.1.tgz", + "integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A==" + }, + "@grpc/grpc-js": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.6.tgz", + "integrity": "sha512-v7+LQFbqZKmd/Tvf5/j1Xlbq6jXL/4d+gUtm2TNX4QiEC3ELWADmGr2dGlUyLl6aKTuYfsN72vAsO5zmavYkEg==", + "requires": { + "@types/node": ">=12.12.47" + } + }, + "@grpc/proto-loader": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.4.tgz", + "integrity": "sha512-7xvDvW/vJEcmLUltCUGOgWRPM8Oofv0eCFSVMuKqaqWJaXSzmB+m9hiyqe34QofAl4WAzIKUZZlinIF9FOHyTQ==", + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.10.0", + "yargs": "^16.1.1" + }, + "dependencies": { + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "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==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } + } + }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -23761,6 +24718,60 @@ } } }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, "@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -24424,6 +25435,11 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==" }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, "@types/match-sorter": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@types/match-sorter/-/match-sorter-6.0.0.tgz", @@ -27652,6 +28668,11 @@ "entities": "^2.0.0" } }, + "dom-storage": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", + "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==" + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -29059,6 +30080,28 @@ "path-exists": "^4.0.0" } }, + "firebase": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.8.1.tgz", + "integrity": "sha512-dzqQn3wwHhsStsD2gDs3XfSJ/SIqv5IA9Ht+MySnvrIsljk0V8bI/+EMPsh0h2VlYPSk51bmyNQZ4LvuSKNvlA==", + "requires": { + "@firebase/analytics": "0.6.16", + "@firebase/app": "0.6.29", + "@firebase/app-check": "0.2.1", + "@firebase/app-types": "0.6.3", + "@firebase/auth": "0.16.8", + "@firebase/database": "0.10.9", + "@firebase/firestore": "2.3.10", + "@firebase/functions": "0.6.14", + "@firebase/installations": "0.4.31", + "@firebase/messaging": "0.7.15", + "@firebase/performance": "0.4.17", + "@firebase/polyfill": "0.3.36", + "@firebase/remote-config": "0.1.42", + "@firebase/storage": "0.6.1", + "@firebase/util": "1.2.0" + } + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -29970,6 +31013,11 @@ "postcss": "^7.0.14" } }, + "idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, "identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", @@ -31987,6 +33035,11 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -32039,6 +33092,11 @@ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -32490,6 +33548,11 @@ "tslib": "^2.0.3" } }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, "node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -34354,6 +35417,11 @@ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" }, + "promise-polyfill": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", + "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" + }, "prompts": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", @@ -34380,6 +35448,33 @@ } } }, + "protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "requires": { + "@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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "16.4.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.12.tgz", + "integrity": "sha512-zxrTNFl9Z8boMJXs6ieqZP0wAhvkdzmHSxTlJabM16cf5G9xBc1uPRH5Bbv2omEDDiM8MzTfqTJXBf0Ba4xFWA==" + } + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -38967,6 +40062,11 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/client/package.json b/client/package.json index 89a1672..2d1140b 100644 --- a/client/package.json +++ b/client/package.json @@ -17,6 +17,7 @@ "@types/react-table": "^7.7.1", "axios": "^0.21.1", "d3": "^6.7.0", + "firebase": "^8.8.1", "match-sorter": "^6.3.0", "qs": "^6.10.1", "react": "^17.0.2", diff --git a/client/src/firebase.ts b/client/src/firebase.ts new file mode 100644 index 0000000..4600548 --- /dev/null +++ b/client/src/firebase.ts @@ -0,0 +1,13 @@ +import firebase from "firebase/app"; +import "firebase/auth"; + +export const app = firebase.initializeApp({ + apiKey: process.env.REACT_APP_FIREBASE_API_KEY, + authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN, + projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID, + storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET, + messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID, + appId: process.env.REACT_APP_FIREBASE_APP_ID, +}); + +export const auth = app.auth(); From a42a81ec3210b5560fd760afbf53dc8c4d530f2e Mon Sep 17 00:00:00 2001 From: janetxinli Date: Sun, 15 Aug 2021 20:10:01 -0400 Subject: [PATCH 2/6] create context for authentication --- client/src/context/AuthContext.tsx | 56 ++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 client/src/context/AuthContext.tsx diff --git a/client/src/context/AuthContext.tsx b/client/src/context/AuthContext.tsx new file mode 100644 index 0000000..2f9216b --- /dev/null +++ b/client/src/context/AuthContext.tsx @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import React, { useContext, useState, useEffect } from "react"; +import firebase from "firebase"; +import { auth } from "../firebase"; + +// TODO: add types, remove 'any's + +interface AuthContextInterface { + currentUser: firebase.User | null; + signup: any; + login: any; + logout: any; +} + +const AuthContext = React.createContext({} as AuthContextInterface); + +export function useAuth() { + return useContext(AuthContext); +} + +export function AuthProvider({ children }: { children: JSX.Element }) { + const [currentUser, setCurrentUser] = useState(null); + const [loading, setLoading] = useState(true); + + function signup(email: string, password: string): Promise { + return auth.createUserWithEmailAndPassword(email, password); + } + + function login(email: string, password: string): Promise { + return auth.signInWithEmailAndPassword(email, password); + } + + function logout(): Promise { + return auth.signOut(); + } + + // attach an observer for sign-in state + useEffect(() => { + const unsubscribe = auth.onAuthStateChanged((user) => { + setCurrentUser(user); + setLoading(false); + }); + + // unsubscribe from the observer when component is unmounted + return unsubscribe; + }, []); + + const value: AuthContextInterface = { + currentUser, + signup, + login, + logout, + }; + + return {!loading && children}; +} From 268bb7886b0e1969b016c9ac37ef03a6391aeec6 Mon Sep 17 00:00:00 2001 From: janetxinli Date: Sun, 22 Aug 2021 15:31:55 -0400 Subject: [PATCH 3/6] Add firebase email/password auth --- client/src/App.tsx | 34 ++++--- client/src/components/Alert/index.tsx | 29 ++++++ client/src/components/NavBar/index.tsx | 121 +++++++++++++++++-------- client/src/context/AlertContext.tsx | 29 ++++++ client/src/context/AuthContext.tsx | 6 ++ client/src/firebase.ts | 4 + client/src/index.css | 16 +++- client/src/pages/Login/index.tsx | 76 ++++++++++++++++ client/src/pages/Signup/index.tsx | 95 +++++++++++++++++++ 9 files changed, 357 insertions(+), 53 deletions(-) create mode 100644 client/src/components/Alert/index.tsx create mode 100644 client/src/context/AlertContext.tsx create mode 100644 client/src/pages/Login/index.tsx create mode 100644 client/src/pages/Signup/index.tsx diff --git a/client/src/App.tsx b/client/src/App.tsx index f302df5..7ccc123 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,6 +1,9 @@ import React from "react"; import { BrowserRouter as Router, Route } from "react-router-dom"; +import { AuthProvider } from "./context/AuthContext"; +import { AlertProvider } from "./context/AlertContext"; import Home from "./pages/Home"; +import Alert from "./components/Alert"; import NavBar from "./components/NavBar"; import SampleView from "./pages/RLoop"; import SearchPage from "./pages/SearchPage"; @@ -9,20 +12,29 @@ import ApiReference from "./pages/ApiReference"; import Downloads from "./pages/Downloads"; import Help from "./pages/Help"; import Upload from "./pages/Upload"; +import Signup from "./pages/Signup"; +import Login from "./pages/Login"; function App() { return ( - - - - - - - - - - - + + + + + + + + + + + + + + + + + + ); } diff --git a/client/src/components/Alert/index.tsx b/client/src/components/Alert/index.tsx new file mode 100644 index 0000000..4941ef6 --- /dev/null +++ b/client/src/components/Alert/index.tsx @@ -0,0 +1,29 @@ +import React, { useEffect } from "react"; +import { useAlert } from "../../context/AlertContext"; +import { useAuth } from "../../context/AuthContext"; + +export default function Alert() { + const { alert, setAlert } = useAlert(); + const { currentUser } = useAuth(); + + useEffect(() => { + if (currentUser && !currentUser.emailVerified) { + setAlert({ + type: "info", + message: "Your account is unverified. Check your email for a verification link.", + }); + } else { + setAlert(null); + } + }, [currentUser?.emailVerified]); + + if (alert) { + return ( +
+

{alert.message}

+
+ ); + } + + return null; +} diff --git a/client/src/components/NavBar/index.tsx b/client/src/components/NavBar/index.tsx index d9646a3..ec6829a 100644 --- a/client/src/components/NavBar/index.tsx +++ b/client/src/components/NavBar/index.tsx @@ -1,7 +1,26 @@ import React from "react"; -import { Link } from "react-router-dom"; +import { Link, useHistory } from "react-router-dom"; +import { useAuth } from "../../context/AuthContext"; +import { useAlert } from "../../context/AlertContext"; const NavBar = () => { + const { currentUser, logout } = useAuth(); + const { setAlert } = useAlert(); + + const history = useHistory(); + + async function handleLogout(e: React.FormEvent) { + e.preventDefault(); + try { + await logout(); + setAlert(null); + history.push("/"); + } catch (err) { + // TODO: error handling for failed logout + console.log(err); + } + } + return ( diff --git a/client/src/context/AlertContext.tsx b/client/src/context/AlertContext.tsx new file mode 100644 index 0000000..9cd2e85 --- /dev/null +++ b/client/src/context/AlertContext.tsx @@ -0,0 +1,29 @@ +import React, { useContext, useState } from "react"; + +// TODO: set types + +interface Alert { + message: string; + type: "success" | "danger" | "info"; // bootstrap alert types +} +interface AlertContextInterface { + alert: Alert | null; + setAlert: any; +} + +const AlertContext = React.createContext({} as AlertContextInterface); + +export function useAlert() { + return useContext(AlertContext); +} + +export function AlertProvider({ children }: { children: JSX.Element }): JSX.Element { + const [alert, setAlert] = useState(null); + + const value: AlertContextInterface = { + alert, + setAlert, + }; + + return {children}; +} diff --git a/client/src/context/AuthContext.tsx b/client/src/context/AuthContext.tsx index 2f9216b..46c9167 100644 --- a/client/src/context/AuthContext.tsx +++ b/client/src/context/AuthContext.tsx @@ -8,6 +8,7 @@ import { auth } from "../firebase"; interface AuthContextInterface { currentUser: firebase.User | null; signup: any; + sendEmailVerification: any; login: any; logout: any; } @@ -26,6 +27,10 @@ export function AuthProvider({ children }: { children: JSX.Element }) { return auth.createUserWithEmailAndPassword(email, password); } + function sendEmailVerification(user: firebase.User) { + return user.sendEmailVerification({ url: "http://localhost:3000" }); + } + function login(email: string, password: string): Promise { return auth.signInWithEmailAndPassword(email, password); } @@ -48,6 +53,7 @@ export function AuthProvider({ children }: { children: JSX.Element }) { const value: AuthContextInterface = { currentUser, signup, + sendEmailVerification, login, logout, }; diff --git a/client/src/firebase.ts b/client/src/firebase.ts index 4600548..93b7d53 100644 --- a/client/src/firebase.ts +++ b/client/src/firebase.ts @@ -11,3 +11,7 @@ export const app = firebase.initializeApp({ }); export const auth = app.auth(); + +export const actionCodeSettings = { + url: "http://localhost:3000", +}; diff --git a/client/src/index.css b/client/src/index.css index ec2585e..1f28829 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,13 +1,19 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; +} + +/* global utility classes */ + +.auth-form { + width: 100%; + max-width: 28em; + margin: auto; } diff --git a/client/src/pages/Login/index.tsx b/client/src/pages/Login/index.tsx new file mode 100644 index 0000000..23ff4cf --- /dev/null +++ b/client/src/pages/Login/index.tsx @@ -0,0 +1,76 @@ +import React, { useState } from "react"; +import { Link, useHistory } from "react-router-dom"; +import { useAuth } from "../../context/AuthContext"; + +export default function Login(): JSX.Element { + const { login } = useAuth(); + const history = useHistory(); + + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + try { + setError(""); + setLoading(true); + await login(email, password); + history.push("/"); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + return ( +
+
+

Log In

+ {error && ( +
+ {error} +
+ )} +
+ + setEmail(e.target.value)} + autoComplete="username" + required + /> +
+
+ + setPassword(e.target.value)} + autoComplete="current-password" + required + /> +
+ +

+ Need an account? Sign up +

+
+
+ ); +} diff --git a/client/src/pages/Signup/index.tsx b/client/src/pages/Signup/index.tsx new file mode 100644 index 0000000..fc8b7b0 --- /dev/null +++ b/client/src/pages/Signup/index.tsx @@ -0,0 +1,95 @@ +import React, { useState } from "react"; +import { Link, useHistory } from "react-router-dom"; +import firebase from "firebase"; +import { useAuth } from "../../context/AuthContext"; + +export default function Signup(): JSX.Element { + const { signup, sendEmailVerification } = useAuth(); + const history = useHistory(); + + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [passwordConfirm, setPasswordConfirm] = useState(""); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (password !== passwordConfirm) { + return setError("Passwords do not match"); + } + try { + setError(""); + setLoading(true); + const userData: firebase.auth.UserCredential = await signup(email, password); + await sendEmailVerification(userData.user); + history.push("/"); + } catch (err) { + setError(err.message); + } + + setLoading(false); + }; + + return ( +
+
+

Sign Up

+ {error && ( +
+ {error} +
+ )} +
+ + setEmail(e.target.value)} + required + /> +
+
+ + setPassword(e.target.value)} + required + /> +
Must be at least 6 characters long
+
+
+ + setPasswordConfirm(e.target.value)} + required + /> +
+ +

+ Already have an account? Log in +

+
+
+ ); +} From 892054f7a9aa664cd95fe2dc7af79b02250cdf35 Mon Sep 17 00:00:00 2001 From: janetxinli Date: Sun, 22 Aug 2021 15:32:03 -0400 Subject: [PATCH 4/6] Clean up code --- client/src/pages/Upload/index.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/src/pages/Upload/index.tsx b/client/src/pages/Upload/index.tsx index ccef4e3..f56fdb7 100644 --- a/client/src/pages/Upload/index.tsx +++ b/client/src/pages/Upload/index.tsx @@ -13,7 +13,7 @@ interface FormData { csv: File | null; } -function Upload() { +export default function Upload(): JSX.Element { const [formData, setFormData] = useState({ sampleId: "", sampleCondition: "", @@ -144,7 +144,7 @@ function Upload() { required /> -
+
@@ -193,5 +193,3 @@ function Upload() { ); } - -export default Upload; From 972ab58343f8c80df21d9524bb4a77d427f2c740 Mon Sep 17 00:00:00 2001 From: janetxinli Date: Tue, 31 Aug 2021 10:09:21 -0700 Subject: [PATCH 5/6] Implement Google and Github signin, add types --- client/src/assets/GithubLogo.png | Bin 0 -> 2625 bytes client/src/assets/GoogleLogo.png | Bin 0 -> 93151 bytes client/src/components/Alert/index.tsx | 6 +- client/src/components/NavBar/index.tsx | 7 +-- .../components/SigninButton/index.module.css | 15 +++++ client/src/components/SigninButton/index.tsx | 43 +++++++++++++++ client/src/context/AlertContext.tsx | 8 +-- client/src/context/AuthContext.tsx | 52 ++++++++++++++---- client/src/firebase.ts | 6 +- client/src/pages/Login/index.tsx | 19 ++++++- client/src/pages/Signup/index.tsx | 8 ++- 11 files changed, 132 insertions(+), 32 deletions(-) create mode 100644 client/src/assets/GithubLogo.png create mode 100644 client/src/assets/GoogleLogo.png create mode 100644 client/src/components/SigninButton/index.module.css create mode 100644 client/src/components/SigninButton/index.tsx diff --git a/client/src/assets/GithubLogo.png b/client/src/assets/GithubLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..182a1a3f734fc1b7d712c68b04c29bad9460d6cd GIT binary patch literal 2625 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 m>V7``AngC?K=1-zU;hXBP!ya1 literal 0 HcmV?d00001 diff --git a/client/src/components/Alert/index.tsx b/client/src/components/Alert/index.tsx index 4941ef6..545b25d 100644 --- a/client/src/components/Alert/index.tsx +++ b/client/src/components/Alert/index.tsx @@ -4,10 +4,10 @@ import { useAuth } from "../../context/AuthContext"; export default function Alert() { const { alert, setAlert } = useAlert(); - const { currentUser } = useAuth(); + const { currentUser, isVerified } = useAuth(); useEffect(() => { - if (currentUser && !currentUser.emailVerified) { + if (currentUser && !isVerified()) { setAlert({ type: "info", message: "Your account is unverified. Check your email for a verification link.", @@ -15,7 +15,7 @@ export default function Alert() { } else { setAlert(null); } - }, [currentUser?.emailVerified]); + }, [currentUser]); if (alert) { return ( diff --git a/client/src/components/NavBar/index.tsx b/client/src/components/NavBar/index.tsx index ec6829a..b9ba2a5 100644 --- a/client/src/components/NavBar/index.tsx +++ b/client/src/components/NavBar/index.tsx @@ -4,7 +4,7 @@ import { useAuth } from "../../context/AuthContext"; import { useAlert } from "../../context/AlertContext"; const NavBar = () => { - const { currentUser, logout } = useAuth(); + const { currentUser, isVerified, logout } = useAuth(); const { setAlert } = useAlert(); const history = useHistory(); @@ -16,8 +16,7 @@ const NavBar = () => { setAlert(null); history.push("/"); } catch (err) { - // TODO: error handling for failed logout - console.log(err); + setAlert({ type: "danger", message: "Failed to sign out. Please try again." }); } } @@ -57,7 +56,7 @@ const NavBar = () => { Download - {currentUser && currentUser.emailVerified && ( + {isVerified() && (
  • Upload diff --git a/client/src/components/SigninButton/index.module.css b/client/src/components/SigninButton/index.module.css new file mode 100644 index 0000000..b3ffa83 --- /dev/null +++ b/client/src/components/SigninButton/index.module.css @@ -0,0 +1,15 @@ +.signInButton { + padding: 0.5em; + display: flex; + align-items: center; + justify-content: center; +} + +.signInButton:hover { + background-image: linear-gradient(white, #f8f9fa) +} + +.signInLogo { + height: 1.5em; + padding-right: 0.5em; +} diff --git a/client/src/components/SigninButton/index.tsx b/client/src/components/SigninButton/index.tsx new file mode 100644 index 0000000..238a7b1 --- /dev/null +++ b/client/src/components/SigninButton/index.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { useHistory } from "react-router-dom"; +import firebase from "firebase"; +import styles from "./index.module.css"; + +export default function SignInButton({ + provider, + logo, + handleSignIn, + setError, +}: { + provider: string; + logo: string; + handleSignIn: () => Promise; + setError: (error: string) => void; +}): JSX.Element { + const history = useHistory(); + + const handleSigninWithProvider = async ( + e: React.FormEvent, + signInFunction: () => Promise + ) => { + e.preventDefault(); + try { + setError(""); + await signInFunction(); + history.push("/"); + } catch (err) { + setError(err.message); + } + }; + + return ( + + ); +} diff --git a/client/src/context/AlertContext.tsx b/client/src/context/AlertContext.tsx index 9cd2e85..cc7ded0 100644 --- a/client/src/context/AlertContext.tsx +++ b/client/src/context/AlertContext.tsx @@ -1,19 +1,17 @@ import React, { useContext, useState } from "react"; -// TODO: set types - interface Alert { message: string; - type: "success" | "danger" | "info"; // bootstrap alert types + type: "success" | "danger" | "info"; // matches bootstrap alert types } interface AlertContextInterface { alert: Alert | null; - setAlert: any; + setAlert: (alert: Alert | null) => void; } const AlertContext = React.createContext({} as AlertContextInterface); -export function useAlert() { +export function useAlert(): AlertContextInterface { return useContext(AlertContext); } diff --git a/client/src/context/AuthContext.tsx b/client/src/context/AuthContext.tsx index 46c9167..76d4f60 100644 --- a/client/src/context/AuthContext.tsx +++ b/client/src/context/AuthContext.tsx @@ -1,21 +1,24 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ import React, { useContext, useState, useEffect } from "react"; import firebase from "firebase"; -import { auth } from "../firebase"; - -// TODO: add types, remove 'any's +import { auth, googleAuthProvider, githubAuthProvider } from "../firebase"; interface AuthContextInterface { currentUser: firebase.User | null; - signup: any; - sendEmailVerification: any; - login: any; - logout: any; + signup: (email: string, password: string) => Promise; + sendEmailVerification: (user: firebase.User) => Promise; + loginWithEmailAndPAssword: ( + email: string, + password: string + ) => Promise; + signInWithGoogle: () => Promise; + signInWithGithub: () => Promise; + isVerified: () => boolean; + logout: () => Promise; } const AuthContext = React.createContext({} as AuthContextInterface); -export function useAuth() { +export function useAuth(): AuthContextInterface { return useContext(AuthContext); } @@ -27,18 +30,40 @@ export function AuthProvider({ children }: { children: JSX.Element }) { return auth.createUserWithEmailAndPassword(email, password); } - function sendEmailVerification(user: firebase.User) { + function sendEmailVerification(user: firebase.User): Promise { return user.sendEmailVerification({ url: "http://localhost:3000" }); } - function login(email: string, password: string): Promise { + function loginWithEmailAndPAssword( + email: string, + password: string + ): Promise { return auth.signInWithEmailAndPassword(email, password); } + async function signInWithGoogle(): Promise { + return auth.signInWithPopup(googleAuthProvider); + } + + function signInWithGithub(): Promise { + return auth.signInWithPopup(githubAuthProvider); + } + function logout(): Promise { return auth.signOut(); } + function isVerified(): boolean { + if (currentUser) { + // Only password auth needs email verification + if (currentUser.providerData[0] && currentUser.providerData[0].providerId === "password") { + return currentUser.emailVerified; + } + return true; + } + return false; + } + // attach an observer for sign-in state useEffect(() => { const unsubscribe = auth.onAuthStateChanged((user) => { @@ -54,7 +79,10 @@ export function AuthProvider({ children }: { children: JSX.Element }) { currentUser, signup, sendEmailVerification, - login, + loginWithEmailAndPAssword, + signInWithGoogle, + signInWithGithub, + isVerified, logout, }; diff --git a/client/src/firebase.ts b/client/src/firebase.ts index 93b7d53..bd2076d 100644 --- a/client/src/firebase.ts +++ b/client/src/firebase.ts @@ -12,6 +12,6 @@ export const app = firebase.initializeApp({ export const auth = app.auth(); -export const actionCodeSettings = { - url: "http://localhost:3000", -}; +export const googleAuthProvider = new firebase.auth.GoogleAuthProvider(); + +export const githubAuthProvider = new firebase.auth.GithubAuthProvider(); diff --git a/client/src/pages/Login/index.tsx b/client/src/pages/Login/index.tsx index 23ff4cf..260bb0f 100644 --- a/client/src/pages/Login/index.tsx +++ b/client/src/pages/Login/index.tsx @@ -1,9 +1,12 @@ import React, { useState } from "react"; import { Link, useHistory } from "react-router-dom"; import { useAuth } from "../../context/AuthContext"; +import SigninButton from "../../components/SigninButton"; +import GoogleLogo from "../../assets/GoogleLogo.png"; +import GithubLogo from "../../assets/GithubLogo.png"; export default function Login(): JSX.Element { - const { login } = useAuth(); + const { loginWithEmailAndPAssword, signInWithGoogle, signInWithGithub } = useAuth(); const history = useHistory(); const [email, setEmail] = useState(""); @@ -16,7 +19,7 @@ export default function Login(): JSX.Element { try { setError(""); setLoading(true); - await login(email, password); + await loginWithEmailAndPAssword(email, password); history.push("/"); } catch (err) { setError(err.message); @@ -34,6 +37,18 @@ export default function Login(): JSX.Element { {error}
  • )} + +