diff --git a/package-lock.json b/package-lock.json index 907a567..5bbcfe1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -177,6 +177,16 @@ "@types/express": "*" } }, + "@types/csurf": { + "version": "1.9.35", + "resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.9.35.tgz", + "integrity": "sha512-2EVN+Bt2Vd8u+11xeJ64BjCYVOlhqaob82FPAw8VzOOWAYfP8TFvB7RD67CShEz45JXiI+38mlNJHKrArCzFMw==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/express-serve-static-core": "*" + } + }, "@types/dotenv": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-6.1.1.tgz", @@ -215,6 +225,16 @@ "@types/range-parser": "*" } }, + "@types/express-session": { + "version": "1.15.14", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.15.14.tgz", + "integrity": "sha512-7kVzFTT0Jy0zmUYDt9ik76XbcqyS9NalV4gn4eLwhk1nGQn+lS/HjPODhG3Oi/GBR2w1LQHUdkz/5KICYMACiw==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/node": "*" + } + }, "@types/fs-capacitor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz", @@ -1625,6 +1645,28 @@ "source-map": "~0.6.0" } }, + "cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "dev": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -1910,12 +1952,84 @@ "randomfill": "^1.0.3" } }, + "csrf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", + "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.6", + "uid-safe": "2.1.5" + } + }, + "css-loader": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.2.0.tgz", + "integrity": "sha512-QTF3Ud5H7DaZotgdcJjGMvyDj5F3Pn1j/sC6VBEOVp94cbwqyIBdcs/quzj4MC1BKQSrTpQznegH/5giYbhnCQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.17", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.1.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.0", + "schema-utils": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "schema-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.4.1.tgz", + "integrity": "sha512-RqYLpkPZX5Oc3fw/kHHHyP56fg5Y+XBpIpV8nCg0znIALfq3OH+Ea9Hfeac9BAMwG5IICltiZ0vxFvJQONfA5w==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, "cssesc": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", "dev": true }, + "csurf": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.10.0.tgz", + "integrity": "sha512-fh725p0R83wA5JukCik5hdEko/LizW/Vl7pkKDa1WJUVCosg141mqaAWCScB+nkEaRMFMGbutHMOr6oBNc/j9A==", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "csrf": "3.1.0", + "http-errors": "~1.7.2" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + } + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1931,6 +2045,16 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "dasherize": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", @@ -2274,6 +2398,50 @@ "is-symbol": "^1.0.2" } }, + "es5-ext": { + "version": "0.10.51", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz", + "integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "^1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz", + "integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.51" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2326,6 +2494,16 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -2456,6 +2634,33 @@ "pino-http": "^4.0.0" } }, + "express-session": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.2.tgz", + "integrity": "sha512-oy0sRsdw6n93E9wpCNWKRnSsxYnSDX9Dnr9mhZgqUEEorzcq5nshGYSZ4ZReHFhKQ80WI5iVUUSPW7u3GaKauw==", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.1.2", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -3749,6 +3954,15 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -4223,6 +4437,15 @@ "yallist": "^3.0.2" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "luxon": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.19.2.tgz", @@ -4320,6 +4543,22 @@ "p-is-promise": "^2.0.0" } }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -4614,6 +4853,12 @@ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4828,6 +5073,11 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5087,6 +5337,15 @@ "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.5.1.tgz", "integrity": "sha512-nqUTo8y9T0VhiJoWC0sK0+2S8hYDiu7CdH0Z9ijPi2iikiQ44mfcAFxEJxfvF8H3h/bDBvXthtOQPIB3pLWIow==" }, + "pg-monitor": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-1.2.2.tgz", + "integrity": "sha512-CZdBt32t2SOuzhj0aYG8MfOBeT0u/a/UDpnBhr//9XWUQ1k7XWlzOCZda90VTNYWawjOYFduhWVFJ+bWTHlH+g==", + "dev": true, + "requires": { + "cli-color": "1.4.0" + } + }, "pg-pool": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.7.tgz", @@ -5251,6 +5510,85 @@ } } }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz", + "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" + }, + "dependencies": { + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-scope": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", + "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "dependencies": { + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, "postcss-selector-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", @@ -5262,6 +5600,12 @@ "uniq": "^1.0.1" } }, + "postcss-value-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz", + "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==", + "dev": true + }, "postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -5554,6 +5898,11 @@ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.2.tgz", "integrity": "sha512-FXTaCkwvpIlkdKeGDNgcq07SXWS383noQUuZjvdE1QcTt+eLuqof6/BDiEPqB59FWLie/l91+HtlJSw7iCViSA==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -5830,6 +6179,11 @@ "inherits": "^2.0.1" } }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", @@ -6556,6 +6910,16 @@ "setimmediate": "^1.0.4" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -6802,6 +7166,11 @@ "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", "dev": true }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" + }, "tsutils": { "version": "2.29.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", @@ -6827,6 +7196,12 @@ "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz", "integrity": "sha1-RXbBzuXi1j0gf+5S8boCgZSAvHU=" }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -6871,6 +7246,14 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", diff --git a/package.json b/package.json index 27bab8d..47bfa70 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,12 @@ "apollo-server-express": "^2.9.3", "argon2": "^0.24.1", "cookie-parser": "^1.4.4", + "csurf": "^1.10.0", "dataloader": "^1.4.0", "dotenv": "^8.1.0", "express": "^4.17.1", "express-pino-logger": "^4.0.0", + "express-session": "^1.16.2", "graphql": "^14.5.7", "helmet": "^3.21.1", "http-errors": "^1.7.3", @@ -37,15 +39,19 @@ }, "devDependencies": { "@types/cookie-parser": "^1.4.2", + "@types/csurf": "^1.9.35", "@types/dotenv": "^6.1.1", "@types/express": "^4.17.1", "@types/express-pino-logger": "^4.0.1", + "@types/express-session": "^1.15.14", "@types/helmet": "0.0.44", "@types/http-errors": "^1.6.2", "@types/luxon": "^1.15.2", "@types/node": "^12.7.5", "@types/pino": "^5.8.10", "@types/webpack-dev-middleware": "^2.0.3", + "css-loader": "^3.2.0", + "pg-monitor": "^1.2.2", "pino-pretty": "^3.2.1", "ts-loader": "^6.2.0", "ts-node-dev": "^1.0.0-pre.43", diff --git a/samples.http b/samples.http index 3a8a411..d225f3c 100644 --- a/samples.http +++ b/samples.http @@ -10,11 +10,11 @@ Content-type: application/json ### -GET {{ baseUrl }}/auth/bootstrap HTTP/1.1 +GET {{ baseUrl }}/bootstrap HTTP/1.1 ### -POST {{ baseUrl }}/auth/bootstrap HTTP/1.1 +POST {{ baseUrl }}/bootstrap HTTP/1.1 Content-Type: application/json { diff --git a/src/db/index.ts b/src/db/index.ts index 805fea7..0746025 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -18,6 +18,7 @@ import { MigrationRepository, UserRepository } from "@kredens/db/repos"; +import monitor from "pg-monitor"; import pgPromise, { IDatabase, IInitOptions } from "pg-promise"; type ExtendedProtocol = IDatabase & Extensions; @@ -30,5 +31,6 @@ const initOptions: IInitOptions = { }; const pgp: pgPromise.IMain = pgPromise(initOptions); +monitor.attach(initOptions); const db: ExtendedProtocol = pgp(process.env.PG_CONNECTION_STRING); export { db, pgp }; diff --git a/src/index.ts b/src/index.ts index 84b3845..1afa74e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,9 +17,12 @@ import { server as graphqlServer } from "@kredens/api"; import { db } from "@kredens/db"; import logger from "@kredens/logger"; import indexRouter from "@kredens/routes/"; +import bootstrapRouter from "@kredens/routes/bootstrap"; import cookieParser from "cookie-parser"; +import csrf from "csurf"; import express from "express"; import pinoExpress from "express-pino-logger"; +import session, { SessionOptions } from "express-session"; import helmet from "helmet"; import createHttpError from "http-errors"; @@ -37,6 +40,19 @@ async function main() { app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); + const sessionOptions: SessionOptions = { + resave: false, + saveUninitialized: false, + secret: process.env.SECRET + }; + + if (app.get("env") === "production") { + app.set("trust proxy", 1); + sessionOptions.cookie.secure = true; + } + app.use(session(sessionOptions)); + app.use("/bootstrap", bootstrapRouter); + app.use(csrf()); if (app.settings.env === "development") { const webpack = require("webpack"); // tslint:disable-line:no-implicit-dependencies diff --git a/src/routes/auth.ts b/src/routes/auth.ts index 04e1b62..11f4529 100644 --- a/src/routes/auth.ts +++ b/src/routes/auth.ts @@ -13,14 +13,17 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import { box, unbox } from "@kredens/crypto"; import { db } from "@kredens/db"; import express from "express"; -import createHttpError from "http-errors"; -import { DateTime } from "luxon"; const router = express.Router(); +router.get("/", async (req, res, next) => { + res.render("login", { + csrfToken: req.csrfToken() + }); +}); + router.post("/", async (req, res, next) => { const userID = await db.users.login(req.body.email, req.body.password); if (userID.isSome()) { @@ -30,35 +33,4 @@ router.post("/", async (req, res, next) => { } }); -interface Token { - expires: string; -} - -router.get("/bootstrap", async (req, res, next) => { - const token: Token = { - expires: DateTime.local() - .plus({ hours: 2 }) - .toISO() - }; - req.log.info("Token issued", { token: box(token) }); -}); - -router.post("/bootstrap", async (req, res, next) => { - const token: Token = unbox(req.body.token); - const expired = DateTime.fromISO(token.expires).diffNow(); - if (expired.as("milliseconds") < 0) { - next(createHttpError(401)); - return; - } - - const email: string = req.body.email; - const password: string = req.body.password; - - if (!email || !password || password.length < 8) { - res.send("Please provide an email and a password longer than 8 characters"); - return; - } - await db.users.create(email, password); -}); - export default router; diff --git a/src/routes/bootstrap.ts b/src/routes/bootstrap.ts new file mode 100644 index 0000000..6250f1d --- /dev/null +++ b/src/routes/bootstrap.ts @@ -0,0 +1,40 @@ +import { box, unbox } from "@kredens/crypto"; +import { db } from "@kredens/db"; +import express from "express"; +import createHttpError from "http-errors"; +import { DateTime } from "luxon"; + +interface Token { + expires: string; +} + +const router = express.Router(); + +router.get("/", async (req, res, next) => { + const token: Token = { + expires: DateTime.local() + .plus({ hours: 2 }) + .toISO() + }; + req.log.info("Token issued", { token: box(token) }); +}); + +router.post("/", async (req, res, next) => { + const token: Token = unbox(req.body.token); + const expired = DateTime.fromISO(token.expires).diffNow(); + if (expired.as("milliseconds") < 0) { + next(createHttpError(401)); + return; + } + + const email: string = req.body.email; + const password: string = req.body.password; + + if (!email || !password || password.length < 8) { + res.send("Please provide an email and a password longer than 8 characters"); + return; + } + await db.users.create(email, password); +}); + +export default router; diff --git a/views/layout.pug b/views/layout.pug new file mode 100644 index 0000000..befcb35 --- /dev/null +++ b/views/layout.pug @@ -0,0 +1,5 @@ +html + head + title Kredens - #{title} + body + block content diff --git a/views/login.pug b/views/login.pug new file mode 100644 index 0000000..4a40149 --- /dev/null +++ b/views/login.pug @@ -0,0 +1,12 @@ +extends layout.pug + +block content + form(method="post") + input(type="hidden", name="_csrf", "value"=csrfToken) + p + label(for="email") Email + input(type="email", name="email") + p + label(for="password") Password + input(type="password", name="password") + input(type="submit") \ No newline at end of file