diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..840414d --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +data/ +*.mmdb + +### Node ### +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Dependency directories +node_modules/ +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# dotenv environment variables file +.env +.env.test +.env*.local + +# rollup.js default build output +dist/ + + +### IDE ### +.idea +*.iml + + +### Linux ### +*~ +.fuse_hidden* + + +### macOS ### +.DS_Store +.AppleDouble +.LSOverride +._* diff --git a/package-lock.json b/package-lock.json index c2c4e63..c460dd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -237,12 +237,11 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "axios": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", - "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" + "follow-redirects": "^1.10.0" } }, "backoff": { @@ -267,9 +266,9 @@ } }, "bl": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", - "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -410,12 +409,12 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", - "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", "requires": { "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "color-string": "^1.5.4" } }, "color-convert": { @@ -432,9 +431,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -832,6 +831,15 @@ "resolved": "https://registry.npmjs.org/express-unless/-/express-unless-0.3.1.tgz", "integrity": "sha1-JVfBRudb65A+LSR/m1ugFFJpbiA=" }, + "express-validator": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.10.0.tgz", + "integrity": "sha512-gDtepU94EpUzgFvKO/8JzjZ4uqIF4xHekjYtcNgFDiBK6Hob3MQhPU8s/c3NaWd1xi5e5nA0oVmOJ0b0ZBO36Q==", + "requires": { + "lodash": "^4.17.20", + "validator": "^13.5.2" + } + }, "express-ws": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-4.0.0.tgz", @@ -875,22 +883,9 @@ } }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" }, "forever-agent": { "version": "0.6.1", @@ -922,14 +917,6 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - } - }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -1054,11 +1041,6 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -1329,23 +1311,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "minipass": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz", - "integrity": "sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minizlib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz", - "integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -1430,11 +1395,6 @@ "xtend": "^4.0.0" } }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" - }, "napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", @@ -1446,13 +1406,18 @@ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, "node-abi": { - "version": "2.19.3", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.3.tgz", - "integrity": "sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.21.0.tgz", + "integrity": "sha512-smhrivuPqEM3H5LmnY3KU6HfYv0u4QklgAxfFyRNujKUzbUcYZ+Jc2EhukB9SRcD2VpqhxM7n/MIcp1Ua1/JMg==", "requires": { "semver": "^5.4.1" } }, + "node-addon-api": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", + "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" + }, "nodemailer": { "version": "6.4.6", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.6.tgz", @@ -1542,9 +1507,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "prebuild-install": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", - "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.1.tgz", + "integrity": "sha512-M+cKwofFlHa5VpTWub7GLg5RLcunYIcLqtY5pKcls/u7xaAb8FrXZ520qY8rkpYy5xw90tYCyMO0MP5ggzR3Sw==", "requires": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", @@ -1552,15 +1517,26 @@ "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", - "node-abi": "^2.7.0", + "node-abi": "^2.21.0", "noop-logger": "^0.1.1", "npmlog": "^4.0.1", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^3.0.3", "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0", - "which-pm-runs": "^1.0.0" + "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + } } }, "precond": { @@ -1778,25 +1754,42 @@ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, "sharp": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.23.4.tgz", - "integrity": "sha512-fJMagt6cT0UDy9XCsgyLi0eiwWWhQRxbwGmqQT6sY8Av4s0SVsT/deg8fobBQCTDU5iXRgz0rAeXoE2LBZ8g+Q==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.3.tgz", + "integrity": "sha512-NdEJ9S6AMr8Px0zgtFo1TJjMK/ROMU92MkDtYn2BBrDjIx3YfH9TUyGdzPC+I/L619GeYQc690Vbaxc5FPCCWg==", "requires": { - "color": "^3.1.2", + "array-flatten": "^3.0.0", + "color": "^3.1.3", "detect-libc": "^1.0.3", - "nan": "^2.14.0", + "node-addon-api": "^3.0.2", "npmlog": "^4.1.2", - "prebuild-install": "^5.3.3", - "semver": "^6.3.0", - "simple-get": "^3.1.0", - "tar": "^5.0.5", + "prebuild-install": "^6.0.0", + "semver": "^7.3.2", + "simple-get": "^4.0.0", + "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" }, "dependencies": { + "array-flatten": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", + "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -1806,18 +1799,33 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "simple-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.0.tgz", + "integrity": "sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==", "requires": { - "decompress-response": "^4.2.0", + "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } } }, "simple-swizzle": { @@ -1894,19 +1902,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, - "tar": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.5.tgz", - "integrity": "sha512-MNIgJddrV2TkuwChwcSNds/5E9VijOiw7kAc1y5hTNJoLDSuIyid2QtLYiCYNnICebpuvjhPQZsXwUL0O3l7OQ==", - "requires": { - "chownr": "^1.1.3", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.0", - "mkdirp": "^0.5.0", - "yallist": "^4.0.0" - } - }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -1919,9 +1914,9 @@ } }, "tar-stream": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", - "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -2097,6 +2092,11 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, + "validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2125,11 +2125,6 @@ "defaults": "^1.0.3" } }, - "which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" - }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", diff --git a/package.json b/package.json index 8ec6d2c..7062ea3 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@turf/simplify": "^5.1.5", - "axios": "^0.19.0", + "axios": "^0.21.1", "carrier": "^0.3.0", "csv-parse": "^4.6.3", "diacritics": "^1.3.0", @@ -20,6 +20,7 @@ "express-bearer-token": "^2.4.0", "express-cache-controller": "^1.1.0", "express-jwt": "^5.3.1", + "express-validator": "^6.10.0", "express-ws": "^4.0.0", "hasha": "^5.1.0", "htmlparser2": "^3.10.1", diff --git a/server.js b/server.js index e6df558..ffe62af 100644 --- a/server.js +++ b/server.js @@ -11,6 +11,7 @@ const RbnReceiver = require('./rbn'); const db = require('./db'); const alerts = require('./alerts'); const geoexport = require('./geoexport'); +const users = require('./users'); const activations = require('./activations'); const utils = require('./utils'); const photos_router = require('./photos_router') @@ -36,6 +37,7 @@ app.use('/ws', wsManager.router); app.use('/alerts', alerts); app.use('/geoexport', geoexport); app.use('/activations', activations); +app.use('/users', users); app.use('/photos', photos_router); app.use('/tracks', tracks_router); diff --git a/users.js b/users.js new file mode 100644 index 0000000..06c2770 --- /dev/null +++ b/users.js @@ -0,0 +1,217 @@ +const express = require("express"); +const {body, validationResult} = require('express-validator'); +const config = require('./config') +const jwt = require("express-jwt"); +const jwksRsa = require("jwks-rsa"); +const db = require("./db"); +const summitUtils = require('./summits'); + +let router = express.Router(); +module.exports = router; + +let jwtCallback = jwt({ + secret: jwksRsa.expressJwtSecret({ + cache: true, + rateLimit: true, + jwksRequestsPerMinute: 5, + jwksUri: config.sso.jwksUri + }) +}); + +const DB_COLLECTION_USERS = "users"; + +router.get("/me", jwtCallback, (req, res) => { + const reqUserId = req.user.userid; + if (!reqUserId) { + return res.status(401).send("Missing userid in SSO token").end(); + } + + db.getDb().collection(DB_COLLECTION_USERS).findOne({userid: reqUserId}, (err, user) => { + if (err) { + return res.status(500).end(); + } + + if (!user) { + return res.status(404).end(); + } + + let summitObjectList = user.userSummits.map(userSummit => { + userSummit.summit = {code: userSummit.code}; + delete userSummit.code; + return userSummit; + }) + summitUtils.lookupSummits(summitObjectList) + .then(userDataWithSummits => { + user.userSummits = userDataWithSummits; + return res.json(user); + }); + }); +}); + +router.post("/me/settings", + jwtCallback, + (req, res) => { + + const reqUserId = req.user.userid; + if (!reqUserId) { + return res.status(401).send("Missing userid in SSO token").end(); + } + + const user = Object.assign({}, + req.body.mapServer && {mapServer: req.body.mapServer}, + req.body.altitudeUnits && {altitudeUnits: req.body.altitudeUnits}, + req.body.spotPrefs && {spotPrefs: req.body.spotPrefs}, + req.body.editAlertPrefs && {editAlertPrefs: req.body.editAlertPrefs} + ); + + db.getDb().collection(DB_COLLECTION_USERS).updateOne( + {userid: reqUserId}, + {$set: user}, + {upsert: true} + ); + + return res.status(200).end(); + }); + +router.get("/me/tags", jwtCallback, (req, res) => { + const reqUserId = req.user.userid; + if (!reqUserId) { + return res.status(401).send("Missing userid in SSO token").end(); + } + + db.getDb().collection(DB_COLLECTION_USERS).aggregate([ + { $match: {userid: reqUserId} }, + { $unwind: '$userSummits' }, + { $unwind: '$userSummits.tags' }, + { $match: { 'userSummits.tags': { $not: {$size: 0} }}}, + { $group: { _id: '$userSummits.tags', count: { $sum: 1 } } } + ]).toArray().then(tagList => { + if(!tagList || tagList.length === 0) { + return res.json([]); + } + + return res.json(tagList.map(tagItem => { + return {tag: tagItem._id, count: tagItem.count} + })); + }).catch(() => { + return res.status(500).end(); + }) +}); + +router.get("/me/summits/tags", jwtCallback, (req, res) => { + const reqUserId = req.user.userid; + if (!reqUserId) { + return res.status(401).send("Missing userid in SSO token").end(); + } + + let queryParam = req.query.q ? req.query.q : [] + if(!Array.isArray(queryParam)) { + queryParam = [queryParam]; + } + + db.getDb().collection(DB_COLLECTION_USERS).aggregate([ + { $match: {userid: reqUserId} }, + { $unwind: '$userSummits' }, + { $match: { 'userSummits.tags': { $in: queryParam } }}, + { $group: { _id: '$userid', codes: { $push: '$userSummits.code' } } } + ]).toArray().then(summitCodeList => { + if (!summitCodeList || summitCodeList.length !== 1 || + !summitCodeList[0].codes || summitCodeList[0].codes.length === 0) { + return res.json([]); + } + + let summitObjectList = summitCodeList[0].codes.map(code => { + return {summit: {code: code}}; + }); + summitUtils.lookupSummits(summitObjectList) + .then(lookedUpSummits => { + + return res.json(lookedUpSummits.map(lookedUpSummit => {return lookedUpSummit.summit})); + }) + }).catch(err => { + return res.status(500).end(); + }) +}); + + + +router.get("/me/summit/:association/:code", jwtCallback, (req, res) => { + const reqUserId = req.user.userid; + if (!reqUserId) { + return res.status(401).send("Missing userid in SSO token").end(); + } + + const code = req.params.association + "/" + req.params.code + db.getDb().collection(DB_COLLECTION_USERS).aggregate([ + { $match: {userid: reqUserId} }, + { $unwind: '$userSummits' }, + { $match: { 'userSummits.code': { $in: [code] } }}, + { $project: { _id: '$userid', userSummit: '$userSummits' } } + ]).toArray().then(userSummits => { + if (!userSummits || userSummits.length === 0) { + return res.json({ + summit: {code: code}, + isBookmarked: false, + notes: "", + tags: [] + }) + } + + if(userSummits.length !== 1) { + return res.status(500).end() + } + + summitUtils.lookupSummits([{summit: {code: userSummits[0].userSummit.code}}]) + .then(summitDetails => { + let requestedUserSummit = userSummits[0]; + delete requestedUserSummit.userSummit.code; + requestedUserSummit.userSummit.summit = summitDetails[0].summit; + return res.json(requestedUserSummit.userSummit); + }) + }).catch(err => { + return res.status(500).end(); + }); +}); + +router.post("/me/summit", + jwtCallback, + body("code").isString(), + body("isBookmarked").isBoolean(), + body("notes").optional().trim().default(""), + body("tags").isArray(), + body("tags.*").isString(), + (req, res) => { + + const reqUserId = req.user.userid; + if (!reqUserId) { + return res.status(401).send("Missing userid in SSO token").end(); + } + + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({errors: errors.array()}); + } + + const newSummitData = { + code: req.body.code, + isBookmarked: req.body.isBookmarked, + notes: req.body.notes, + tags: req.body.tags + }; + + db.getDb().collection(DB_COLLECTION_USERS).updateOne( + {userid: reqUserId}, + {$pull: {userSummits: {code: newSummitData.code}}} + ); + + if (newSummitData.isBookmarked === true || newSummitData.notes !== "") { + db.getDb().collection(DB_COLLECTION_USERS).updateOne( + {userid: reqUserId}, + {$push: {userSummits: newSummitData}}, + {upsert: true} + ); + return res.status(201).end(); + } else { + return res.status(204).end(); + } + });