From 4d3bf7bba0d4ac7a0f1e7697fe3485890569202d Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 15 Feb 2023 16:52:54 -0500 Subject: [PATCH 01/93] major: backend setup --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 2 + app.js | 22 + package-lock.json | 2479 +++++++++++++++++++++++++++++++++++++ package.json | 25 + public/css/styles.css | 16 + views/home.ejs | 16 + views/partials/footer.ejs | 4 + views/partials/header.ejs | 12 + 9 files changed, 2576 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 app.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/css/styles.css create mode 100644 views/home.ejs create mode 100644 views/partials/footer.ejs create mode 100644 views/partials/header.ejs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7008296163b9525f479b9079a0c11b11b96a0e5d GIT binary patch literal 6148 zcmeHKOHRWu5FM9-%4bn_EPaLEAXMQ5y#Pvs04b3ps=^A%mw@xI=0@yz(#QULTCowX84T^ z@Z23yM{BC6q2ByqLi2{^cD7iCw$o9(@3yz0EUP9|uw%8vhnJ7H%b`#GtxtE??}ryA z9nvFGyP+pqZI&0O*E8qIouB2cJE=XtN@~6MHe`wI@yOHKu)x`w7z4(DG4SUY;5`&F zITf_h7%&Emfh_~PKX@o(p%?|z)`22D0f1welc1iiY(UQjV4)ZVVSzXa1xl#XCx(-7 z*uDA{icwI)$)%q0AMM%c3&o}0VfV?MTp?(sF<=bj3>?Vkl+XXGuiyW9kbM~g#=yT~ zz>UjAImeLnY#j`a&sq=14.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.272.0.tgz", + "integrity": "sha512-uMjRWcNvX7SoGaVn0mXWD43+Z1awPahQwGW3riDLfXHZdOgw2oFDhD3Jg5jQ8OzQLUfDvArhE3WyZwlS4muMuQ==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.272.0", + "@aws-sdk/config-resolver": "3.272.0", + "@aws-sdk/credential-provider-node": "3.272.0", + "@aws-sdk/fetch-http-handler": "3.272.0", + "@aws-sdk/hash-node": "3.272.0", + "@aws-sdk/invalid-dependency": "3.272.0", + "@aws-sdk/middleware-content-length": "3.272.0", + "@aws-sdk/middleware-endpoint": "3.272.0", + "@aws-sdk/middleware-host-header": "3.272.0", + "@aws-sdk/middleware-logger": "3.272.0", + "@aws-sdk/middleware-recursion-detection": "3.272.0", + "@aws-sdk/middleware-retry": "3.272.0", + "@aws-sdk/middleware-serde": "3.272.0", + "@aws-sdk/middleware-signing": "3.272.0", + "@aws-sdk/middleware-stack": "3.272.0", + "@aws-sdk/middleware-user-agent": "3.272.0", + "@aws-sdk/node-config-provider": "3.272.0", + "@aws-sdk/node-http-handler": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/smithy-client": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/url-parser": "3.272.0", + "@aws-sdk/util-base64": "3.208.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.208.0", + "@aws-sdk/util-defaults-mode-browser": "3.272.0", + "@aws-sdk/util-defaults-mode-node": "3.272.0", + "@aws-sdk/util-endpoints": "3.272.0", + "@aws-sdk/util-retry": "3.272.0", + "@aws-sdk/util-user-agent-browser": "3.272.0", + "@aws-sdk/util-user-agent-node": "3.272.0", + "@aws-sdk/util-utf8": "3.254.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.272.0.tgz", + "integrity": "sha512-xn9a0IGONwQIARmngThoRhF1lLGjHAD67sUaShgIMaIMc6ipVYN6alWG1VuUpoUQ6iiwMEt0CHdfCyLyUV/fTA==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/config-resolver": "3.272.0", + "@aws-sdk/fetch-http-handler": "3.272.0", + "@aws-sdk/hash-node": "3.272.0", + "@aws-sdk/invalid-dependency": "3.272.0", + "@aws-sdk/middleware-content-length": "3.272.0", + "@aws-sdk/middleware-endpoint": "3.272.0", + "@aws-sdk/middleware-host-header": "3.272.0", + "@aws-sdk/middleware-logger": "3.272.0", + "@aws-sdk/middleware-recursion-detection": "3.272.0", + "@aws-sdk/middleware-retry": "3.272.0", + "@aws-sdk/middleware-serde": "3.272.0", + "@aws-sdk/middleware-stack": "3.272.0", + "@aws-sdk/middleware-user-agent": "3.272.0", + "@aws-sdk/node-config-provider": "3.272.0", + "@aws-sdk/node-http-handler": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/smithy-client": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/url-parser": "3.272.0", + "@aws-sdk/util-base64": "3.208.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.208.0", + "@aws-sdk/util-defaults-mode-browser": "3.272.0", + "@aws-sdk/util-defaults-mode-node": "3.272.0", + "@aws-sdk/util-endpoints": "3.272.0", + "@aws-sdk/util-retry": "3.272.0", + "@aws-sdk/util-user-agent-browser": "3.272.0", + "@aws-sdk/util-user-agent-node": "3.272.0", + "@aws-sdk/util-utf8": "3.254.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.272.0.tgz", + "integrity": "sha512-ECcXu3xoa1yggnGKMTh29eWNHiF/wC6r5Uqbla22eOOosyh0+Z6lkJ3JUSLOUKCkBXA4Cs/tJL9UDFBrKbSlvA==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/config-resolver": "3.272.0", + "@aws-sdk/fetch-http-handler": "3.272.0", + "@aws-sdk/hash-node": "3.272.0", + "@aws-sdk/invalid-dependency": "3.272.0", + "@aws-sdk/middleware-content-length": "3.272.0", + "@aws-sdk/middleware-endpoint": "3.272.0", + "@aws-sdk/middleware-host-header": "3.272.0", + "@aws-sdk/middleware-logger": "3.272.0", + "@aws-sdk/middleware-recursion-detection": "3.272.0", + "@aws-sdk/middleware-retry": "3.272.0", + "@aws-sdk/middleware-serde": "3.272.0", + "@aws-sdk/middleware-stack": "3.272.0", + "@aws-sdk/middleware-user-agent": "3.272.0", + "@aws-sdk/node-config-provider": "3.272.0", + "@aws-sdk/node-http-handler": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/smithy-client": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/url-parser": "3.272.0", + "@aws-sdk/util-base64": "3.208.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.208.0", + "@aws-sdk/util-defaults-mode-browser": "3.272.0", + "@aws-sdk/util-defaults-mode-node": "3.272.0", + "@aws-sdk/util-endpoints": "3.272.0", + "@aws-sdk/util-retry": "3.272.0", + "@aws-sdk/util-user-agent-browser": "3.272.0", + "@aws-sdk/util-user-agent-node": "3.272.0", + "@aws-sdk/util-utf8": "3.254.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.272.0.tgz", + "integrity": "sha512-kigxCxURp3WupufGaL/LABMb7UQfzAQkKcj9royizL3ItJ0vw5kW/JFrPje5IW1mfLgdPF7PI9ShOjE0fCLTqA==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/config-resolver": "3.272.0", + "@aws-sdk/credential-provider-node": "3.272.0", + "@aws-sdk/fetch-http-handler": "3.272.0", + "@aws-sdk/hash-node": "3.272.0", + "@aws-sdk/invalid-dependency": "3.272.0", + "@aws-sdk/middleware-content-length": "3.272.0", + "@aws-sdk/middleware-endpoint": "3.272.0", + "@aws-sdk/middleware-host-header": "3.272.0", + "@aws-sdk/middleware-logger": "3.272.0", + "@aws-sdk/middleware-recursion-detection": "3.272.0", + "@aws-sdk/middleware-retry": "3.272.0", + "@aws-sdk/middleware-sdk-sts": "3.272.0", + "@aws-sdk/middleware-serde": "3.272.0", + "@aws-sdk/middleware-signing": "3.272.0", + "@aws-sdk/middleware-stack": "3.272.0", + "@aws-sdk/middleware-user-agent": "3.272.0", + "@aws-sdk/node-config-provider": "3.272.0", + "@aws-sdk/node-http-handler": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/smithy-client": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/url-parser": "3.272.0", + "@aws-sdk/util-base64": "3.208.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.208.0", + "@aws-sdk/util-defaults-mode-browser": "3.272.0", + "@aws-sdk/util-defaults-mode-node": "3.272.0", + "@aws-sdk/util-endpoints": "3.272.0", + "@aws-sdk/util-retry": "3.272.0", + "@aws-sdk/util-user-agent-browser": "3.272.0", + "@aws-sdk/util-user-agent-node": "3.272.0", + "@aws-sdk/util-utf8": "3.254.0", + "fast-xml-parser": "4.0.11", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/config-resolver": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.272.0.tgz", + "integrity": "sha512-Dr4CffRVNsOp3LRNdpvcH6XuSgXOSLblWliCy/5I86cNl567KVMxujVx6uPrdTXYs2h1rt3MNl6jQGnAiJeTbw==", + "optional": true, + "dependencies": { + "@aws-sdk/signature-v4": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/util-config-provider": "3.208.0", + "@aws-sdk/util-middleware": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-cognito-identity": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.272.0.tgz", + "integrity": "sha512-rVx0rtQjbiYCM0nah2rB/2ut2YJYPpRr1AbW/Hd4r/PI+yiusrmXAwuT4HIW2yr34zsQMPi1jZ3WHN9Rn9mzlg==", + "optional": true, + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.272.0.tgz", + "integrity": "sha512-QI65NbLnKLYHyTYhXaaUrq6eVsCCrMUb05WDA7+TJkWkjXesovpjc8vUKgFiLSxmgKmb2uOhHNcDyObKMrYQFw==", + "optional": true, + "dependencies": { + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-imds": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.272.0.tgz", + "integrity": "sha512-wwAfVY1jTFQEfxVfdYD5r5ieYGl+0g4nhekVxNMqE8E1JeRDd18OqiwAflzpgBIqxfqvCUkf+vl5JYyacMkNAQ==", + "optional": true, + "dependencies": { + "@aws-sdk/node-config-provider": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/url-parser": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.272.0.tgz", + "integrity": "sha512-iE3CDzK5NcupHYjfYjBdY1JCy8NLEoRUsboEjG0i0gy3S3jVpDeVHX1dLVcL/slBFj6GiM7SoNV/UfKnJf3Gaw==", + "optional": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.272.0", + "@aws-sdk/credential-provider-imds": "3.272.0", + "@aws-sdk/credential-provider-process": "3.272.0", + "@aws-sdk/credential-provider-sso": "3.272.0", + "@aws-sdk/credential-provider-web-identity": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/shared-ini-file-loader": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.272.0.tgz", + "integrity": "sha512-FI8uvwM1IxiRSvbkdKv8DZG5vxU3ezaseTaB1fHWTxEUFb0pWIoHX9oeOKer9Fj31SOZTCNAaYFURbSRuZlm/w==", + "optional": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.272.0", + "@aws-sdk/credential-provider-imds": "3.272.0", + "@aws-sdk/credential-provider-ini": "3.272.0", + "@aws-sdk/credential-provider-process": "3.272.0", + "@aws-sdk/credential-provider-sso": "3.272.0", + "@aws-sdk/credential-provider-web-identity": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/shared-ini-file-loader": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.272.0.tgz", + "integrity": "sha512-hiCAjWWm2PeBFp5cjkxqyam/XADjiS+e7GzwC34TbZn3LisS0uoweLojj9tD11NnnUhyhbLteUvu5+rotOLwrg==", + "optional": true, + "dependencies": { + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/shared-ini-file-loader": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.272.0.tgz", + "integrity": "sha512-hwYaulyiU/7chKKFecxCeo0ls6Dxs7h+5EtoYcJJGvfpvCncyOZF35t00OAsCd3Wo7HkhhgfpGdb6dmvCNQAZQ==", + "optional": true, + "dependencies": { + "@aws-sdk/client-sso": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/shared-ini-file-loader": "3.272.0", + "@aws-sdk/token-providers": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.272.0.tgz", + "integrity": "sha512-ImrHMkcgneGa/HadHAQXPwOrX26sAKuB8qlMxZF/ZCM2B55u8deY+ZVkVuraeKb7YsahMGehPFOfRAF6mvFI5Q==", + "optional": true, + "dependencies": { + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-providers": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.272.0.tgz", + "integrity": "sha512-ucd6Xq6aBMf+nM4uz5zkjL11mwaE5BV1Q4hkulaGu2v1dRA8n6zhLJk/sb4hOJ7leelqMJMErlbQ2T3MkYvlJQ==", + "optional": true, + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.272.0", + "@aws-sdk/client-sso": "3.272.0", + "@aws-sdk/client-sts": "3.272.0", + "@aws-sdk/credential-provider-cognito-identity": "3.272.0", + "@aws-sdk/credential-provider-env": "3.272.0", + "@aws-sdk/credential-provider-imds": "3.272.0", + "@aws-sdk/credential-provider-ini": "3.272.0", + "@aws-sdk/credential-provider-node": "3.272.0", + "@aws-sdk/credential-provider-process": "3.272.0", + "@aws-sdk/credential-provider-sso": "3.272.0", + "@aws-sdk/credential-provider-web-identity": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/shared-ini-file-loader": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/fetch-http-handler": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.272.0.tgz", + "integrity": "sha512-1Qhm9e0RbS1Xf4CZqUbQyUMkDLd7GrsRXWIvm9b86/vgeV8/WnjO3CMue9D51nYgcyQORhYXv6uVjAYCWbUExA==", + "optional": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/querystring-builder": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/util-base64": "3.208.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/hash-node": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.272.0.tgz", + "integrity": "sha512-40dwND+iAm3VtPHPZu7/+CIdVJFk2s0cWZt1lOiMPMSXycSYJ45wMk7Lly3uoqRx0uWfFK5iT2OCv+fJi5jTng==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "@aws-sdk/util-buffer-from": "3.208.0", + "@aws-sdk/util-utf8": "3.254.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/invalid-dependency": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.272.0.tgz", + "integrity": "sha512-ysW6wbjl1Y78txHUQ/Tldj2Rg1BI7rpMO9B9xAF6yAX3mQ7t6SUPQG/ewOGvH2208NBIl3qP5e/hDf0Q6r/1iw==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/is-array-buffer": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", + "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-content-length": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.272.0.tgz", + "integrity": "sha512-sAbDZSTNmLX+UTGwlUHJBWy0QGQkiClpHwVFXACon+aG0ySLNeRKEVYs6NCPYldw4cj6hveLUn50cX44ukHErw==", + "optional": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-endpoint": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.272.0.tgz", + "integrity": "sha512-Dk3JVjj7SxxoUKv3xGiOeBksvPtFhTDrVW75XJ98Ymv8gJH5L1sq4hIeJAHRKogGiRFq2J73mnZSlM9FVXEylg==", + "optional": true, + "dependencies": { + "@aws-sdk/middleware-serde": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/signature-v4": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/url-parser": "3.272.0", + "@aws-sdk/util-config-provider": "3.208.0", + "@aws-sdk/util-middleware": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.272.0.tgz", + "integrity": "sha512-Q8K7bMMFZnioUXpxn57HIt4p+I63XaNAawMLIZ5B4F2piyukbQeM9q2XVKMGwqLvijHR8CyP5nHrtKqVuINogQ==", + "optional": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.272.0.tgz", + "integrity": "sha512-u2SQ0hWrFwxbxxYMG5uMEgf01pQY5jauK/LYWgGIvuCmFgiyRQQP3oN7kkmsxnS9MWmNmhbyQguX2NY02s5e9w==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.272.0.tgz", + "integrity": "sha512-Gp/eKWeUWVNiiBdmUM2qLkBv+VLSJKoWAO+aKmyxxwjjmWhE0FrfA1NQ1a3g+NGMhRbAfQdaYswRAKsul70ISg==", + "optional": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-retry": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.272.0.tgz", + "integrity": "sha512-pCGvHM7C76VbO/dFerH+Vwf7tGv7j+e+eGrvhQ35mRghCtfIou/WMfTZlD1TNee93crrAQQVZKjtW3dMB3WCzg==", + "optional": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/service-error-classification": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/util-middleware": "3.272.0", + "@aws-sdk/util-retry": "3.272.0", + "tslib": "^2.3.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.272.0.tgz", + "integrity": "sha512-VvYPg7LrDIjUOWueSzo2wBzcNG7dw+cmzV6zAKaLxf0RC5jeAP4hE0OzDiiZfDrjNghEzgq/V+0NO+LewqYL9Q==", + "optional": true, + "dependencies": { + "@aws-sdk/middleware-signing": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/signature-v4": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-serde": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.272.0.tgz", + "integrity": "sha512-kW1uOxgPSwtXPB5rm3QLdWomu42lkYpQL94tM1BjyFOWmBLO2lQhk5a7Dw6HkTozT9a+vxtscLChRa6KZe61Hw==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.272.0.tgz", + "integrity": "sha512-4LChFK4VAR91X+dupqM8fQqYhFGE0G4Bf9rQlVTgGSbi2KUOmpqXzH0/WKE228nKuEhmH8+Qd2VPSAE2JcyAUA==", + "optional": true, + "dependencies": { + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/signature-v4": "3.272.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/util-middleware": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-stack": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.272.0.tgz", + "integrity": "sha512-jhwhknnPBGhfXAGV5GXUWfEhDFoP/DN8MPCO2yC5OAxyp6oVJ8lTPLkZYMTW5VL0c0eG44dXpF4Ib01V+PlDrQ==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.272.0.tgz", + "integrity": "sha512-Qy7/0fsDJxY5l0bEk7WKDfqb4Os/sCAgFR2zEvrhDtbkhYPf72ysvg/nRUTncmCbo8tOok4SJii2myk8KMfjjw==", + "optional": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/node-config-provider": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.272.0.tgz", + "integrity": "sha512-YYCIBh9g1EQo7hm2l22HX5Yr9RoPQ2RCvhzKvF1n1e8t1QH4iObQrYUtqHG4khcm64Cft8C5MwZmgzHbya5Z6Q==", + "optional": true, + "dependencies": { + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/shared-ini-file-loader": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/node-http-handler": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.272.0.tgz", + "integrity": "sha512-VrW9PjhhngeyYp4yGYPe5S0vgZH6NwU3Po9xAgayUeE37Inr7LS1YteFMHdpgsUUeNXnh7d06CXqHo1XjtqOKA==", + "optional": true, + "dependencies": { + "@aws-sdk/abort-controller": "3.272.0", + "@aws-sdk/protocol-http": "3.272.0", + "@aws-sdk/querystring-builder": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/property-provider": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.272.0.tgz", + "integrity": "sha512-V1pZTaH5eqpAt8O8CzbItHhOtzIfFuWymvwZFkAtwKuaHpnl7jjrTouV482zoq8AD/fF+VVSshwBKYA7bhidIw==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/protocol-http": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.272.0.tgz", + "integrity": "sha512-4JQ54v5Yn08jspNDeHo45CaSn1CvTJqS1Ywgr79eU6jBExtguOWv6LNtwVSBD9X37v88iqaxt8iu1Z3pZZAJeg==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/querystring-builder": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.272.0.tgz", + "integrity": "sha512-ndo++7GkdCj5tBXE6rGcITpSpZS4PfyV38wntGYAlj9liL1omk3bLZRY6uzqqkJpVHqbg2fD7O2qHNItzZgqhw==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "@aws-sdk/util-uri-escape": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/querystring-parser": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.272.0.tgz", + "integrity": "sha512-5oS4/9n6N1LZW9tI3qq/0GnCuWoOXRgcHVB+AJLRBvDbEe+GI+C/xK1tKLsfpDNgsQJHc4IPQoIt4megyZ/1+A==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/service-error-classification": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.272.0.tgz", + "integrity": "sha512-REoltM1LK9byyIufLqx9znhSolPcHQgVHIA2S0zu5sdt5qER4OubkLAXuo4MBbisUTmh8VOOvIyUb5ijZCXq1w==", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/shared-ini-file-loader": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.272.0.tgz", + "integrity": "sha512-lzFPohp5sy2XvwFjZIzLVCRpC0i5cwBiaXmFzXYQZJm6FSCszHO4ax+m9yrtlyVFF/2YPWl+/bzNthy4aJtseA==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.272.0.tgz", + "integrity": "sha512-pWxnHG1NqJWMwlhJ6NHNiUikOL00DHROmxah6krJPMPq4I3am2KY2Rs/8ouWhnEXKaHAv4EQhSALJ+7Mq5S4/A==", + "optional": true, + "dependencies": { + "@aws-sdk/is-array-buffer": "3.201.0", + "@aws-sdk/types": "3.272.0", + "@aws-sdk/util-hex-encoding": "3.201.0", + "@aws-sdk/util-middleware": "3.272.0", + "@aws-sdk/util-uri-escape": "3.201.0", + "@aws-sdk/util-utf8": "3.254.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/smithy-client": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.272.0.tgz", + "integrity": "sha512-pvdleJ3kaRvyRw2pIZnqL85ZlWBOZrPKmR9I69GCvlyrfdjRBhbSjIEZ+sdhZudw0vdHxq25AGoLUXhofVLf5Q==", + "optional": true, + "dependencies": { + "@aws-sdk/middleware-stack": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.272.0.tgz", + "integrity": "sha512-0GISJ4IKN2rXvbSddB775VjBGSKhYIGQnAdMqbvxi9LB6pSvVxcH9aIL28G0spiuL+dy3yGQZ8RlJPAyP9JW9A==", + "optional": true, + "dependencies": { + "@aws-sdk/client-sso-oidc": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/shared-ini-file-loader": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.272.0.tgz", + "integrity": "sha512-MmmL6vxMGP5Bsi+4wRx4mxYlU/LX6M0noOXrDh/x5FfG7/4ZOar/nDxqDadhJtNM88cuWVHZWY59P54JzkGWmA==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/url-parser": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.272.0.tgz", + "integrity": "sha512-vX/Tx02PlnQ/Kgtf5TnrNDHPNbY+amLZjW0Z1d9vzAvSZhQ4i9Y18yxoRDIaDTCNVRDjdhV8iuctW+05PB5JtQ==", + "optional": true, + "dependencies": { + "@aws-sdk/querystring-parser": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-base64": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz", + "integrity": "sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg==", + "optional": true, + "dependencies": { + "@aws-sdk/util-buffer-from": "3.208.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-body-length-browser": { + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", + "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-body-length-node": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz", + "integrity": "sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-buffer-from": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz", + "integrity": "sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw==", + "optional": true, + "dependencies": { + "@aws-sdk/is-array-buffer": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-config-provider": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz", + "integrity": "sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-defaults-mode-browser": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.272.0.tgz", + "integrity": "sha512-W8ZVJSZRuUBg8l0JEZzUc+9fKlthVp/cdE+pFeF8ArhZelOLCiaeCrMaZAeJusaFzIpa6cmOYQAjtSMVyrwRtg==", + "optional": true, + "dependencies": { + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/types": "3.272.0", + "bowser": "^2.11.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/util-defaults-mode-node": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.272.0.tgz", + "integrity": "sha512-U0NTcbMw6KFk7uz/avBmfxQSTREEiX6JDMH68oN/3ux4AICd2I4jHyxnloSWGuiER1FxZf1dEJ8ZTwy8Ibl21Q==", + "optional": true, + "dependencies": { + "@aws-sdk/config-resolver": "3.272.0", + "@aws-sdk/credential-provider-imds": "3.272.0", + "@aws-sdk/node-config-provider": "3.272.0", + "@aws-sdk/property-provider": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.272.0.tgz", + "integrity": "sha512-c4MPUaJt2G6gGpoiwIOqDfUa98c1J63RpYvf/spQEKOtC/tF5Gfqlxuq8FnAl5lHnrqj1B9ZXLLxFhHtDR0IiQ==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-hex-encoding": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", + "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.208.0.tgz", + "integrity": "sha512-iua1A2+P7JJEDHVgvXrRJSvsnzG7stYSGQnBVphIUlemwl6nN5D+QrgbjECtrbxRz8asYFHSzhdhECqN+tFiBg==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-middleware": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.272.0.tgz", + "integrity": "sha512-Abw8m30arbwxqmeMMha5J11ESpHUNmCeSqSzE8/C4B8jZQtHY4kq7f+upzcNIQ11lsd+uzBEzNG3+dDRi0XOJQ==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-retry": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.272.0.tgz", + "integrity": "sha512-Ngha5414LR4gRHURVKC9ZYXsEJhMkm+SJ+44wlzOhavglfdcKKPUsibz5cKY1jpUV7oKECwaxHWpBB8r6h+hOg==", + "optional": true, + "dependencies": { + "@aws-sdk/service-error-classification": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@aws-sdk/util-uri-escape": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", + "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.272.0.tgz", + "integrity": "sha512-Lp5QX5bH6uuwBlIdr7w7OAcAI50ttyskb++yUr9i+SPvj6RI2dsfIBaK4mDg1qUdM5LeUdvIyqwj3XHjFKAAvA==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.272.0", + "bowser": "^2.11.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.272.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.272.0.tgz", + "integrity": "sha512-ljK+R3l+Q1LIHrcR+Knhk0rmcSkfFadZ8V+crEGpABf/QUQRg7NkZMsoe814tfBO5F7tMxo8wwwSdaVNNHtoRA==", + "optional": true, + "dependencies": { + "@aws-sdk/node-config-provider": "3.272.0", + "@aws-sdk/types": "3.272.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8": { + "version": "3.254.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.254.0.tgz", + "integrity": "sha512-14Kso/eIt5/qfIBmhEL9L1IfyUqswjSTqO2mY7KOzUZ9SZbwn3rpxmtkhmATkRjD7XIlLKaxBkI7tU9Zjzj8Kw==", + "optional": true, + "dependencies": { + "@aws-sdk/util-buffer-from": "3.208.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@types/node": { + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/fast-xml-parser": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz", + "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==", + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.13.0.tgz", + "integrity": "sha512-+taZ/bV8d1pYuHL4U+gSwkhmDrwkWbH1l4aah4YpmpscMwgFBkufIKxgP/G7m87/NUuQzc2Z75ZTI7ZOyqZLbw==", + "dependencies": { + "bson": "^4.7.0", + "mongodb-connection-string-url": "^2.5.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=12.9.0" + }, + "optionalDependencies": { + "@aws-sdk/credential-providers": "^3.186.0", + "saslprep": "^1.0.3" + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongoose": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.9.1.tgz", + "integrity": "sha512-hOz1ZWV0w6WEVLrj89Wpk7PXDYtDDF6k7/NX79lY5iKqeFtZsceBXW8xW59YFNcW5O3cH32hQ8IbDlhgyBsDMA==", + "dependencies": { + "bson": "^4.7.0", + "kareem": "2.5.1", + "mongodb": "4.13.0", + "mpath": "0.9.0", + "mquery": "4.0.3", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.3.tgz", + "integrity": "sha512-J5heI+P08I6VJ2Ky3+33IpCdAvlYGTSUjwTPxkAr8i8EoduPMBX2OY/wa3IKZIQl7MU4SbFk8ndgSKyB/cl1zA==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "optional": true + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..158c5d1ee --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "allpurdue", + "version": "1.0.0", + "description": "CS 307 Project", + "main": "app.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/kabrap/allpurdue.git" + }, + "author": "Team 10", + "license": "ISC", + "bugs": { + "url": "https://github.com/kabrap/allpurdue/issues" + }, + "homepage": "https://github.com/kabrap/allpurdue#readme", + "dependencies": { + "ejs": "^3.1.8", + "express": "^4.18.2", + "mongoose": "^6.9.1", + "nodemon": "^2.0.20" + } +} diff --git a/public/css/styles.css b/public/css/styles.css new file mode 100644 index 000000000..a5e3a444d --- /dev/null +++ b/public/css/styles.css @@ -0,0 +1,16 @@ + +body { + background-color: #E8ECEF; +} + +.centered { + padding-top: 200px; + text-align: center; +} + +.secret-text { + text-align: center; + font-size: 2rem; + color: #fff; + background-color: #000; +} diff --git a/views/home.ejs b/views/home.ejs new file mode 100644 index 000000000..28ea819bd --- /dev/null +++ b/views/home.ejs @@ -0,0 +1,16 @@ +<%- include('partials/header') %> + + +
+
+ +

AllPurdue

+

One stop platform for everything @ Purdue

+
+ Register + Login + +
+
+ +<%- include('partials/footer') %> diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs new file mode 100644 index 000000000..d549cb0f8 --- /dev/null +++ b/views/partials/footer.ejs @@ -0,0 +1,4 @@ + + + + diff --git a/views/partials/header.ejs b/views/partials/header.ejs new file mode 100644 index 000000000..4eb7d90a5 --- /dev/null +++ b/views/partials/header.ejs @@ -0,0 +1,12 @@ + + + + + + AllPurdue + + + + + + From 33ab18c673020d62fc743290e43a99900641d913 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 15 Feb 2023 22:13:41 -0500 Subject: [PATCH 02/93] major: added basic setup for db and mongoose --- app.js | 16 +++++++++++++++- views/landing.ejs | 14 ++++++++++++++ views/login.ejs | 42 ++++++++++++++++++++++++++++++++++++++++++ views/register.ejs | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 views/landing.ejs create mode 100644 views/login.ejs create mode 100644 views/register.ejs diff --git a/app.js b/app.js index 5232f355f..6e0735d63 100644 --- a/app.js +++ b/app.js @@ -6,13 +6,27 @@ const mongoose = require("mongoose"); const app = express(); mongoose.set('strictQuery', false); +mongoose.connect("mongodb://localhost:27017/allPurdueDB"); -mongoose.connect("mongodb://localhost:27017"); app.use(express.static("public")); app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({extended: true})); +// Basic Schema +const schema = new mongoose.Schema({ + email: String, + password: String +}); + +// Simple User Collection +const User = new mongoose.model("User", schema); + +// Sample User for testing +const yash = new User({ email: "abc@123.com", password: "abc"}); + +//yash.save() + app.get('/', function(req, res){ res.render("home"); }) diff --git a/views/landing.ejs b/views/landing.ejs new file mode 100644 index 000000000..d1801ac18 --- /dev/null +++ b/views/landing.ejs @@ -0,0 +1,14 @@ +<%- include('partials/header') %> + +
+
+ +

Welcome to AllPurdue! Here are the categories!!!

+
+ + Log Out + Submit a Secret +
+
+ +<%- include('partials/footer') %> diff --git a/views/login.ejs b/views/login.ejs new file mode 100644 index 000000000..cc9a45956 --- /dev/null +++ b/views/login.ejs @@ -0,0 +1,42 @@ +<%- include('partials/header') %> + +
+

Login

+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+
+ + + +
+
+ +<%- include('partials/footer') %> diff --git a/views/register.ejs b/views/register.ejs new file mode 100644 index 000000000..b4471ebd7 --- /dev/null +++ b/views/register.ejs @@ -0,0 +1,41 @@ +<%- include('partials/header') %> +
+

Register

+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+
+ + + +
+
+ +<%- include('partials/header') %> From 64870c9740c4f256e2d664177ec20d924ca02be4 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 15 Feb 2023 22:19:05 -0500 Subject: [PATCH 03/93] major: added get routes --- app.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 6e0735d63..435768ef4 100644 --- a/app.js +++ b/app.js @@ -22,13 +22,24 @@ const schema = new mongoose.Schema({ // Simple User Collection const User = new mongoose.model("User", schema); -// Sample User for testing -const yash = new User({ email: "abc@123.com", password: "abc"}); - -//yash.save() app.get('/', function(req, res){ res.render("home"); +}); + +// GET Route for Register +app.get('/register', function(req, res) { + res.render("register"); +}) + +// GET Route for Login +app.get('/login', function(req, res) { + res.render("login"); +}) + +// GET Route for Landing +app.get('/landing', function(req, res) { + res.render("landing"); }) app.listen(3000, function() { From 2c0c5f75790482fe064ba90995af629b748309f2 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 15 Feb 2023 22:51:08 -0500 Subject: [PATCH 04/93] major: added register and login routes --- app.js | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 435768ef4..14b41e281 100644 --- a/app.js +++ b/app.js @@ -22,7 +22,7 @@ const schema = new mongoose.Schema({ // Simple User Collection const User = new mongoose.model("User", schema); - +// GET Route for Homes app.get('/', function(req, res){ res.render("home"); }); @@ -32,6 +32,44 @@ app.get('/register', function(req, res) { res.render("register"); }) +// POST Route for Register +app.post('/register', function(req, res) { + const newUser = new User({ + email: req.body.username, + password: req.body.password + }); + newUser.save(function(err) { + if (err) { + console.log(err); + res.sendStatus(500); + } else { + res.render("landing"); + } + }); +}); + +// POST Route for Login +app.post('/login', function(req, res) { + var username = req.body.username; + var userPass = req.body.password; + + User.findOne({email: username}, function(err, userExists) { + if (err) { + console.log(err); + } else { + if (userExists) { + if (userExists.password === userPass) { + res.render("landing"); + } else { + console.log("password mismatch"); + res.redirect("login"); + } + } + } + } + ); +}); + // GET Route for Login app.get('/login', function(req, res) { res.render("login"); From c3d50f291eeefdc687ea1c74d60353b10996f034 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Thu, 16 Feb 2023 13:34:56 -0500 Subject: [PATCH 05/93] major: added password encryption --- app.js | 15 +++++++-- package-lock.json | 85 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 ++ 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 14b41e281..ab5476467 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,10 @@ +require('dotenv').config() + const express = require("express"); const bodyParser = require("body-parser"); const ejs = require("ejs"); const mongoose = require("mongoose"); +const encrypt = require("mongoose-encryption"); const app = express(); @@ -15,10 +18,18 @@ app.use(bodyParser.urlencoded({extended: true})); // Basic Schema const schema = new mongoose.Schema({ - email: String, + email: { + type: String, + unique: true + }, password: String }); +schema.plugin(encrypt, { + secret: process.env.SECRET, + encryptedFields: ['password'] +}); + // Simple User Collection const User = new mongoose.model("User", schema); @@ -41,7 +52,7 @@ app.post('/register', function(req, res) { newUser.save(function(err) { if (err) { console.log(err); - res.sendStatus(500); + res.status(500).json({ error: 'email already exists' }); } else { res.render("landing"); } diff --git a/package-lock.json b/package-lock.json index a0b0537ae..f4558d3ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,11 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", "mongoose": "^6.9.1", + "mongoose-encryption": "^2.1.2", "nodemon": "^2.0.20" } }, @@ -1279,6 +1281,11 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1437,6 +1444,19 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/dotty": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotty/-/dotty-0.1.2.tgz", + "integrity": "sha512-V0EWmKeH3DEhMwAZ+8ZB2Ao4OK6p++Z0hsDtZq3N0+0ZMVqkzrcEGROvOnZpLnvBg5PTNG23JEDLAm64gPaotQ==" + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1826,6 +1846,25 @@ "node": ">=10" } }, + "node_modules/json-stable-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", + "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", + "dependencies": { + "jsonify": "^0.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/kareem": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", @@ -1834,6 +1873,11 @@ "node": ">=12.0.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1949,6 +1993,42 @@ "url": "https://opencollective.com/mongoose" } }, + "node_modules/mongoose-encryption": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mongoose-encryption/-/mongoose-encryption-2.1.2.tgz", + "integrity": "sha512-whc9ZhN8/UjED3qiQKJvQAx/H1Ml3FUpEiyoHLKl4gzhvWorndnRE0sKuQ3fKzuaZDi/rDBN5AI4L/J2Er8Q9Q==", + "dependencies": { + "async": "^2.6.1", + "buffer-equal-constant-time": "^1.0.1", + "dotty": "^0.1.2", + "json-stable-stringify": "^1.0.0", + "mpath": "^0.8.4", + "semver": "^5.5.0", + "underscore": "^1.5.0" + }, + "engines": { + "node": ">=4.4.5" + }, + "peerDependencies": { + "mongoose": ">=5.0.0" + } + }, + "node_modules/mongoose-encryption/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/mongoose-encryption/node_modules/mpath": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", + "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -2422,6 +2502,11 @@ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 158c5d1ee..316cca913 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,11 @@ }, "homepage": "https://github.com/kabrap/allpurdue#readme", "dependencies": { + "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", "mongoose": "^6.9.1", + "mongoose-encryption": "^2.1.2", "nodemon": "^2.0.20" } } From 37087690df4cc23bae76f2e39b6eac8f0c027a95 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Thu, 16 Feb 2023 13:42:25 -0500 Subject: [PATCH 06/93] major: added hashing --- app.js | 11 +++-------- package-lock.json | 32 ++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/app.js b/app.js index ab5476467..afe8df695 100644 --- a/app.js +++ b/app.js @@ -4,7 +4,7 @@ const express = require("express"); const bodyParser = require("body-parser"); const ejs = require("ejs"); const mongoose = require("mongoose"); -const encrypt = require("mongoose-encryption"); +const md5 = require('md5'); const app = express(); @@ -25,11 +25,6 @@ const schema = new mongoose.Schema({ password: String }); -schema.plugin(encrypt, { - secret: process.env.SECRET, - encryptedFields: ['password'] -}); - // Simple User Collection const User = new mongoose.model("User", schema); @@ -47,7 +42,7 @@ app.get('/register', function(req, res) { app.post('/register', function(req, res) { const newUser = new User({ email: req.body.username, - password: req.body.password + password: md5(req.body.password) }); newUser.save(function(err) { if (err) { @@ -62,7 +57,7 @@ app.post('/register', function(req, res) { // POST Route for Login app.post('/login', function(req, res) { var username = req.body.username; - var userPass = req.body.password; + var userPass = md5(req.body.password); User.findOne({email: username}, function(err, userExists) { if (err) { diff --git a/package-lock.json b/package-lock.json index f4558d3ec..204a9083d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", + "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", "nodemon": "^2.0.20" @@ -1340,6 +1341,14 @@ "node": ">=8" } }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1419,6 +1428,14 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -1802,6 +1819,11 @@ "node": ">=8" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1878,6 +1900,16 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", diff --git a/package.json b/package.json index 316cca913..77760210e 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", + "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", "nodemon": "^2.0.20" From 3726d039a724ea895c55180003bc2bbe527d6804 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Sun, 19 Feb 2023 22:39:47 -0500 Subject: [PATCH 07/93] major: revised user schema & added validations --- app.js | 51 ++++- package-lock.json | 538 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + views/register.ejs | 4 + 4 files changed, 585 insertions(+), 9 deletions(-) diff --git a/app.js b/app.js index afe8df695..c2650319b 100644 --- a/app.js +++ b/app.js @@ -16,14 +16,44 @@ app.use(express.static("public")); app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({extended: true})); -// Basic Schema -const schema = new mongoose.Schema({ - email: { +// User Schema + +const schema = new mongoose.Schema( + { + name: { type: String, - unique: true - }, - password: String -}); + required: true, + }, + email: { + type: String, + lowercase: true, + unique: true, + validate: { + validator: validateEmail, + message: () => "Email address already registered.", + }, + required: [true, "User email required"], + }, + password: { + type: String, + required: true, + minLength: 6, + maxLength: 12 + } + }, + { timestamps: true } + ); + + async function validateEmail(email) { + const user = await User.findOne({ email }); + if (user) { + if (User.id === user.id) { + return true; + } + return false; + } + return true; + } // Simple User Collection const User = new mongoose.model("User", schema); @@ -41,14 +71,16 @@ app.get('/register', function(req, res) { // POST Route for Register app.post('/register', function(req, res) { const newUser = new User({ + name: req.body.name, email: req.body.username, password: md5(req.body.password) }); newUser.save(function(err) { if (err) { console.log(err); - res.status(500).json({ error: 'email already exists' }); + res.sendStatus(500); } else { + console.log("User Successfully Registered!"); res.render("landing"); } }); @@ -65,9 +97,10 @@ app.post('/login', function(req, res) { } else { if (userExists) { if (userExists.password === userPass) { + console.log("User Successfully Logged In!"); res.render("landing"); } else { - console.log("password mismatch"); + console.log("Incorrect Password!"); res.redirect("login"); } } diff --git a/package-lock.json b/package-lock.json index 204a9083d..09e2b4483 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "bcrypt": "^5.1.0", "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", @@ -1082,6 +1083,53 @@ "tslib": "^2.3.1" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@types/node": { "version": "18.13.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", @@ -1118,6 +1166,46 @@ "node": ">= 0.6" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1144,6 +1232,23 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -1178,6 +1283,19 @@ } ] }, + "node_modules/bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1375,6 +1493,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1391,11 +1517,24 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1444,6 +1583,11 @@ "ms": "^2.1.1" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1461,6 +1605,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -1493,6 +1645,11 @@ "node": ">=0.10.0" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -1668,6 +1825,33 @@ "node": ">= 0.6" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -1686,6 +1870,25 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/get-intrinsic": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", @@ -1699,6 +1902,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1740,6 +1962,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -1755,6 +1982,39 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1790,6 +2050,15 @@ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -1832,6 +2101,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -1900,6 +2177,39 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", @@ -1978,6 +2288,48 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", + "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mongodb": { "version": "4.13.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.13.0.tgz", @@ -2114,6 +2466,49 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/nodemon": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", @@ -2163,6 +2558,25 @@ "node": ">=0.10.0" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -2182,6 +2596,14 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2190,6 +2612,14 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -2267,6 +2697,19 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2278,6 +2721,20 @@ "node": ">=8.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2372,6 +2829,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -2395,6 +2857,11 @@ "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/simple-update-notifier": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", @@ -2453,6 +2920,38 @@ "node": ">= 0.8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", @@ -2470,6 +2969,22 @@ "node": ">=4" } }, + "node_modules/tar": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2547,6 +3062,11 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -2591,6 +3111,24 @@ "engines": { "node": ">=12" } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index 77760210e..0de206956 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "homepage": "https://github.com/kabrap/allpurdue#readme", "dependencies": { + "bcrypt": "^5.1.0", "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", diff --git a/views/register.ejs b/views/register.ejs index b4471ebd7..f592f1c28 100644 --- a/views/register.ejs +++ b/views/register.ejs @@ -9,6 +9,10 @@
+
+ + +
From 88a57918b83f5c84bb918eb910d7f72f511944d5 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Mon, 20 Feb 2023 01:21:02 -0500 Subject: [PATCH 08/93] major: added session handling --- app.js | 24 ++++++-- package-lock.json | 136 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 6 +- 3 files changed, 159 insertions(+), 7 deletions(-) diff --git a/app.js b/app.js index c2650319b..0c1ae34fd 100644 --- a/app.js +++ b/app.js @@ -5,6 +5,7 @@ const bodyParser = require("body-parser"); const ejs = require("ejs"); const mongoose = require("mongoose"); const md5 = require('md5'); +const session = require('express-session'); const app = express(); @@ -15,9 +16,13 @@ mongoose.connect("mongodb://localhost:27017/allPurdueDB"); app.use(express.static("public")); app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({extended: true})); +app.use(session({ + secret: process.env.SECRET, + resave: false, + saveUninitialized: true +})); // User Schema - const schema = new mongoose.Schema( { name: { @@ -37,8 +42,7 @@ const schema = new mongoose.Schema( password: { type: String, required: true, - minLength: 6, - maxLength: 12 + minLength: 6 } }, { timestamps: true } @@ -68,6 +72,15 @@ app.get('/register', function(req, res) { res.render("register"); }) +// GET Route for Landing +app.get('/landing', function(req, res) { + if (!req.session.user) { + res.render("login"); + } else { + res.render("landing"); + } +}) + // POST Route for Register app.post('/register', function(req, res) { const newUser = new User({ @@ -81,7 +94,7 @@ app.post('/register', function(req, res) { res.sendStatus(500); } else { console.log("User Successfully Registered!"); - res.render("landing"); + res.render("login"); } }); }); @@ -98,7 +111,8 @@ app.post('/login', function(req, res) { if (userExists) { if (userExists.password === userPass) { console.log("User Successfully Logged In!"); - res.render("landing"); + req.session.user = userExists; + res.redirect("/landing"); } else { console.log("Incorrect Password!"); res.redirect("login"); diff --git a/package-lock.json b/package-lock.json index 09e2b4483..6dc7b0bbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,10 +13,14 @@ "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", + "express-session": "^1.17.3", "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", - "nodemon": "^2.0.20" + "nodemon": "^2.0.20", + "passport": "^0.6.0", + "passport-local": "^1.0.0", + "passport-local-mongoose": "^7.1.2" } }, "node_modules/@aws-crypto/ie11-detection": { @@ -1712,6 +1716,45 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "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.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1889,6 +1932,11 @@ "node": ">=10" } }, + "node_modules/generaterr": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/generaterr/-/generaterr-1.5.0.tgz", + "integrity": "sha512-JgcGRv2yUKeboLvvNrq9Bm90P4iJBu7/vd5wSLYqMG5GJ6SxZT46LAAkMfNhQ+EK3jzC+cRBm7P8aUWYyphgcQ==" + }, "node_modules/get-intrinsic": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", @@ -2596,6 +2644,14 @@ "node": ">= 0.8" } }, + "node_modules/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==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2612,6 +2668,55 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-local-mongoose": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/passport-local-mongoose/-/passport-local-mongoose-7.1.2.tgz", + "integrity": "sha512-hNLIKi/6IhElr/PhOze8wLDh7T4+ZYhc8GFWYApLgG7FrjI55tuGZELPtsUBqODz77OwlUUf+ngPgHN09zxGLg==", + "dependencies": { + "generaterr": "^1.5.0", + "passport-local": "^1.0.0", + "scmp": "^2.1.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2625,6 +2730,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2675,6 +2785,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2771,6 +2889,11 @@ "node": ">=6" } }, + "node_modules/scmp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", + "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" + }, "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -3044,6 +3167,17 @@ "node": ">= 0.6" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index 0de206956..2ea2922a4 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,13 @@ "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", + "express-session": "^1.17.3", "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", - "nodemon": "^2.0.20" + "nodemon": "^2.0.20", + "passport": "^0.6.0", + "passport-local": "^1.0.0", + "passport-local-mongoose": "^7.1.2" } } From 359f53eb551c182da5d42d0bed57c9a00d484e6f Mon Sep 17 00:00:00 2001 From: yashnarain Date: Mon, 20 Feb 2023 01:40:50 -0500 Subject: [PATCH 09/93] major: added forgot password setup --- app.js | 4 ++++ views/forgotPassword.ejs | 26 ++++++++++++++++++++++++++ views/login.ejs | 5 +++++ 3 files changed, 35 insertions(+) create mode 100644 views/forgotPassword.ejs diff --git a/app.js b/app.js index 0c1ae34fd..d61f9830c 100644 --- a/app.js +++ b/app.js @@ -123,6 +123,10 @@ app.post('/login', function(req, res) { ); }); +app.get("/forgotPassword", function(req, res) { + res.render("forgotPassword"); +}); + // GET Route for Login app.get('/login', function(req, res) { res.render("login"); diff --git a/views/forgotPassword.ejs b/views/forgotPassword.ejs new file mode 100644 index 000000000..83a988de8 --- /dev/null +++ b/views/forgotPassword.ejs @@ -0,0 +1,26 @@ +<%- include('partials/header') %> + +
+

Forgot Password? Let's Reset!

+ +
+
+
+
+ + + +
+ + +
+ + +
+
+
+ +
+
+ +<%- include('partials/footer') %> diff --git a/views/login.ejs b/views/login.ejs index cc9a45956..a3ffd53f6 100644 --- a/views/login.ejs +++ b/views/login.ejs @@ -20,6 +20,11 @@
+
+ +
+ +
From 2f39e6f98222dfe846d8f9ef5b9e90bafecaf927 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Mon, 20 Feb 2023 01:58:32 -0500 Subject: [PATCH 10/93] major: integrated jwt tokens --- app.js | 29 +++++++++++++++++++- package-lock.json | 57 ++++++++++++++++++++++++++++++++++++++++ package.json | 1 + views/forgotPassword.ejs | 4 +-- 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index d61f9830c..6db174539 100644 --- a/app.js +++ b/app.js @@ -6,6 +6,7 @@ const ejs = require("ejs"); const mongoose = require("mongoose"); const md5 = require('md5'); const session = require('express-session'); +const jwt = require('jsonwebtoken'); const app = express(); @@ -17,7 +18,7 @@ app.use(express.static("public")); app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({extended: true})); app.use(session({ - secret: process.env.SECRET, + secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: true })); @@ -127,6 +128,32 @@ app.get("/forgotPassword", function(req, res) { res.render("forgotPassword"); }); +app.post("/forgotPassword", function(req, res) { + const userEmail = req.body.username; + User.findOne({email: userEmail}, function(err, userExists) { + if (err) { + console.log(err); + res.sendStatus(500); + } else { + if (userExists) { + const secret = process.env.JWT_SECRET + userExists.password; + const payload = { + email: userEmail, + id: userExists.id + }; + const token = jwt.sign(payload, secret, {expiresIn: '15m'}); + const link = `http://localhost:3000/reset-password/${userExists.id}/${token}`; + console.log(link); + return; + } else { + console.log("User not found!"); + res.redirect("/forgotPassword"); + } + } +} +); +}); + // GET Route for Login app.get('/login', function(req, res) { res.render("login"); diff --git a/package-lock.json b/package-lock.json index 6dc7b0bbc..83ed68f99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "ejs": "^3.1.8", "express": "^4.18.2", "express-session": "^1.17.3", + "jsonwebtoken": "^9.0.0", "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", @@ -1630,6 +1631,14 @@ "resolved": "https://registry.npmjs.org/dotty/-/dotty-0.1.2.tgz", "integrity": "sha512-V0EWmKeH3DEhMwAZ+8ZB2Ao4OK6p++Z0hsDtZq3N0+0ZMVqkzrcEGROvOnZpLnvBg5PTNG23JEDLAm64gPaotQ==" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -2212,6 +2221,54 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kareem": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", diff --git a/package.json b/package.json index 2ea2922a4..5cbbb275f 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "ejs": "^3.1.8", "express": "^4.18.2", "express-session": "^1.17.3", + "jsonwebtoken": "^9.0.0", "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", diff --git a/views/forgotPassword.ejs b/views/forgotPassword.ejs index 83a988de8..e15d94ea9 100644 --- a/views/forgotPassword.ejs +++ b/views/forgotPassword.ejs @@ -8,8 +8,8 @@
- -
+ +
From 178573c4bc6bce3eebf7a149e5761cd389a39659 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Mon, 20 Feb 2023 03:15:26 -0500 Subject: [PATCH 11/93] major: sendgrid email integration --- app.js | 232 +++++++++++++++++++++++++++------------------- package-lock.json | 71 ++++++++++++++ package.json | 1 + 3 files changed, 207 insertions(+), 97 deletions(-) diff --git a/app.js b/app.js index 6db174539..6821d5254 100644 --- a/app.js +++ b/app.js @@ -7,16 +7,18 @@ const mongoose = require("mongoose"); const md5 = require('md5'); const session = require('express-session'); const jwt = require('jsonwebtoken'); +const mail = require('@sendgrid/mail'); const app = express(); mongoose.set('strictQuery', false); mongoose.connect("mongodb://localhost:27017/allPurdueDB"); +mail.setApiKey(process.env.MAIL_KEY); app.use(express.static("public")); app.set("view engine", "ejs"); -app.use(bodyParser.urlencoded({extended: true})); +app.use(bodyParser.urlencoded({ extended: true })); app.use(session({ secret: process.env.SESSION_SECRET, resave: false, @@ -25,56 +27,56 @@ app.use(session({ // User Schema const schema = new mongoose.Schema( - { - name: { - type: String, - required: true, - }, - email: { - type: String, - lowercase: true, - unique: true, - validate: { - validator: validateEmail, - message: () => "Email address already registered.", - }, - required: [true, "User email required"], + { + name: { + type: String, + required: true, + }, + email: { + type: String, + lowercase: true, + unique: true, + validate: { + validator: validateEmail, + message: () => "Email address already registered.", }, - password: { - type: String, - required: true, - minLength: 6 - } + required: [true, "User email required"], }, - { timestamps: true } - ); - - async function validateEmail(email) { - const user = await User.findOne({ email }); - if (user) { - if (User.id === user.id) { - return true; - } - return false; + password: { + type: String, + required: true, + minLength: 6 } - return true; + }, + { timestamps: true } +); + +async function validateEmail(email) { + const user = await User.findOne({ email }); + if (user) { + if (User.id === user.id) { + return true; + } + return false; } + return true; +} // Simple User Collection const User = new mongoose.model("User", schema); // GET Route for Homes -app.get('/', function(req, res){ - res.render("home"); +app.get('/', function (req, res) { + res.render("home"); }); // GET Route for Register -app.get('/register', function(req, res) { - res.render("register"); +app.get('/register', function (req, res) { + res.render("register"); }) // GET Route for Landing -app.get('/landing', function(req, res) { +app.get('/landing', function (req, res) { if (!req.session.user) { res.render("login"); } else { @@ -83,87 +85,123 @@ app.get('/landing', function(req, res) { }) // POST Route for Register -app.post('/register', function(req, res) { - const newUser = new User({ - name: req.body.name, - email: req.body.username, - password: md5(req.body.password) - }); - newUser.save(function(err) { - if (err) { - console.log(err); - res.sendStatus(500); - } else { - console.log("User Successfully Registered!"); - res.render("login"); - } - }); +app.post('/register', function (req, res) { + const newUser = new User({ + name: req.body.name, + email: req.body.username, + password: md5(req.body.password) + }); + newUser.save(function (err) { + if (err) { + console.log(err); + res.sendStatus(500); + } else { + console.log("User Successfully Registered!"); + res.render("login"); + } + }); }); // POST Route for Login -app.post('/login', function(req, res) { - var username = req.body.username; - var userPass = md5(req.body.password); - - User.findOne({email: username}, function(err, userExists) { - if (err) { - console.log(err); - } else { - if (userExists) { - if (userExists.password === userPass) { - console.log("User Successfully Logged In!"); - req.session.user = userExists; - res.redirect("/landing"); - } else { - console.log("Incorrect Password!"); - res.redirect("login"); - } - } - } +app.post('/login', function (req, res) { + var username = req.body.username; + var userPass = md5(req.body.password); + + User.findOne({ email: username }, function (err, userExists) { + if (err) { + console.log(err); + } else { + if (userExists) { + if (userExists.password === userPass) { + console.log("User Successfully Logged In!"); + req.session.user = userExists; + res.redirect("/landing"); + } else { + console.log("Incorrect Password!"); + res.redirect("login"); } - ); + } + } + } + ); }); -app.get("/forgotPassword", function(req, res) { +// GET Route for /forgotPassword +app.get("/forgotPassword", function (req, res) { res.render("forgotPassword"); }); -app.post("/forgotPassword", function(req, res) { +global.resetUser; + +// POST Route for /forgotPassword +app.post("/forgotPassword", function (req, res) { const userEmail = req.body.username; - User.findOne({email: userEmail}, function(err, userExists) { + User.findOne({ email: userEmail }, function (err, userExists) { if (err) { - console.log(err); - res.sendStatus(500); + console.log(err); + res.sendStatus(500); } else { - if (userExists) { - const secret = process.env.JWT_SECRET + userExists.password; - const payload = { - email: userEmail, - id: userExists.id - }; - const token = jwt.sign(payload, secret, {expiresIn: '15m'}); - const link = `http://localhost:3000/reset-password/${userExists.id}/${token}`; - console.log(link); - return; - } else { - console.log("User not found!"); - res.redirect("/forgotPassword"); + if (userExists) { + const secret = process.env.JWT_SECRET + userExists.password; + const payload = { + email: userEmail, + id: userExists.id + }; + const token = jwt.sign(payload, secret, { expiresIn: '15m' }); + resetUser = userExists; + const link = `http://localhost:3000/reset-password/${userExists.id}/${token}`; + console.log(userEmail); + const msg = { + to: userEmail, + from: 'agarw236@purdue.edu', + subject: 'AllPurdue Password Reset', + text: `Hello from AllPurdue! Boiler Up! Please click the link to reset your email:${link}. The link is only valid for 15 minutes.` } + mail + .send(msg) + .then(() => { + console.log('Email sent') + }) + .catch((error) => { + console.error(error) + }) + res.send("Link Sent Successfuly! Check your inbox!"); + } else { + console.log("User not found!"); + res.redirect("/forgotPassword"); + } } -} -); + }); +}); + +app.get("/reset-password/:id/:token", function (req, res) { + const { id, token } = req.params; + if (id === global.resetUser.id) { + const secret = process.env.JWT_SECRET + global.resetUser.password; + try { + jwt.verify(token, secret); + console.log("Verified"); + //res.render("reset-password", {email: global.resetUser.email}); + res.send("Verification Successful!"); + } catch (error) { + console.log(error); + } + } else { + console.log("Verification Failed"); + res.sendStatus(500); + } }); // GET Route for Login -app.get('/login', function(req, res) { - res.render("login"); +app.get('/login', function (req, res) { + res.render("login"); }) // GET Route for Landing -app.get('/landing', function(req, res) { - res.render("landing"); +app.get('/landing', function (req, res) { + res.render("landing"); }) -app.listen(3000, function() { - console.log("Server started at Port 3000!"); +app.listen(3000, function () { + console.log("Server started at Port 3000!"); }); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 83ed68f99..ded77a2d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@sendgrid/mail": "^7.7.0", "bcrypt": "^5.1.0", "dotenv": "^16.0.3", "ejs": "^3.1.8", @@ -1135,6 +1136,41 @@ "node": ">=10" } }, + "node_modules/@sendgrid/client": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.7.0.tgz", + "integrity": "sha512-SxH+y8jeAQSnDavrTD0uGDXYIIkFylCo+eDofVmZLQ0f862nnqbC3Vd1ej6b7Le7lboyzQF6F7Fodv02rYspuA==", + "dependencies": { + "@sendgrid/helpers": "^7.7.0", + "axios": "^0.26.0" + }, + "engines": { + "node": "6.* || 8.* || >=10.*" + } + }, + "node_modules/@sendgrid/helpers": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-7.7.0.tgz", + "integrity": "sha512-3AsAxfN3GDBcXoZ/y1mzAAbKzTtUZ5+ZrHOmWQ279AuaFXUNCh9bPnRpN504bgveTqoW+11IzPg3I0WVgDINpw==", + "dependencies": { + "deepmerge": "^4.2.2" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@sendgrid/mail": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-7.7.0.tgz", + "integrity": "sha512-5+nApPE9wINBvHSUxwOxkkQqM/IAAaBYoP9hw7WwgDNQPxraruVqHizeTitVtKGiqWCKm2mnjh4XGN3fvFLqaw==", + "dependencies": { + "@sendgrid/client": "^7.7.0", + "@sendgrid/helpers": "^7.7.0" + }, + "engines": { + "node": "6.* || 8.* || >=10.*" + } + }, "node_modules/@types/node": { "version": "18.13.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", @@ -1264,6 +1300,14 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1588,6 +1632,14 @@ "ms": "^2.1.1" } }, + "node_modules/deepmerge": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", + "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -1861,6 +1913,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", diff --git a/package.json b/package.json index 5cbbb275f..bbeb54fc1 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "homepage": "https://github.com/kabrap/allpurdue#readme", "dependencies": { + "@sendgrid/mail": "^7.7.0", "bcrypt": "^5.1.0", "dotenv": "^16.0.3", "ejs": "^3.1.8", From 30bab0c777b6caf923b7be867d5cd8947811bdb1 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Mon, 20 Feb 2023 16:36:06 -0500 Subject: [PATCH 12/93] major: set up email service using nodemailer --- app.js | 33 ++++++++++++++++++++------------- package-lock.json | 9 +++++++++ package.json | 1 + 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/app.js b/app.js index 6821d5254..4989ed70c 100644 --- a/app.js +++ b/app.js @@ -7,14 +7,22 @@ const mongoose = require("mongoose"); const md5 = require('md5'); const session = require('express-session'); const jwt = require('jsonwebtoken'); -const mail = require('@sendgrid/mail'); +const nodemailer = require('nodemailer'); const app = express(); mongoose.set('strictQuery', false); mongoose.connect("mongodb://localhost:27017/allPurdueDB"); -mail.setApiKey(process.env.MAIL_KEY); - +const transporter = nodemailer.createTransport({ + service: 'gmail', + host: 'smtp.gmail.com', + port: 465, + secure: true, + auth: { + user: 'yashnarainagarwal@gmail.com', + pass: 'process.env.APP_PASS' + } +}); app.use(express.static("public")); app.set("view engine", "ejs"); @@ -152,19 +160,18 @@ app.post("/forgotPassword", function (req, res) { const link = `http://localhost:3000/reset-password/${userExists.id}/${token}`; console.log(userEmail); const msg = { + from: 'yashnarainagarwal@gmail.com', to: userEmail, - from: 'agarw236@purdue.edu', subject: 'AllPurdue Password Reset', - text: `Hello from AllPurdue! Boiler Up! Please click the link to reset your email:${link}. The link is only valid for 15 minutes.` + text: `Hello from AllPurdue! Boiler Up! Please click the link to reset your email:\n${link}.\n The link is only valid for 15 minutes.` } - mail - .send(msg) - .then(() => { - console.log('Email sent') - }) - .catch((error) => { - console.error(error) - }) + transporter.sendMail(msg, function(error, info){ + if (error) { + console.log(error); + } else { + console.log('Email sent: ' + info.response); + } + }); res.send("Link Sent Successfuly! Check your inbox!"); } else { console.log("User not found!"); diff --git a/package-lock.json b/package-lock.json index ded77a2d1..cf9f1b95e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", + "nodemailer": "^6.9.1", "nodemon": "^2.0.20", "passport": "^0.6.0", "passport-local": "^1.0.0", @@ -2685,6 +2686,14 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/nodemailer": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", + "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", diff --git a/package.json b/package.json index bbeb54fc1..831b6c849 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", + "nodemailer": "^6.9.1", "nodemon": "^2.0.20", "passport": "^0.6.0", "passport-local": "^1.0.0", From afeefa185ed3d03d14a0711005cfb731f48520e0 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Mon, 20 Feb 2023 17:02:04 -0500 Subject: [PATCH 13/93] minor: replace email for nodemailer --- app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 4989ed70c..92635979a 100644 --- a/app.js +++ b/app.js @@ -19,8 +19,8 @@ const transporter = nodemailer.createTransport({ port: 465, secure: true, auth: { - user: 'yashnarainagarwal@gmail.com', - pass: 'process.env.APP_PASS' + user: 'allpurdue2023@gmail.com', + pass: process.env.APP_PASS, } }); @@ -160,7 +160,7 @@ app.post("/forgotPassword", function (req, res) { const link = `http://localhost:3000/reset-password/${userExists.id}/${token}`; console.log(userEmail); const msg = { - from: 'yashnarainagarwal@gmail.com', + from: '"Team AllPurdue" allpurdue2023@gmail.com', to: userEmail, subject: 'AllPurdue Password Reset', text: `Hello from AllPurdue! Boiler Up! Please click the link to reset your email:\n${link}.\n The link is only valid for 15 minutes.` From d88ed3ed8a88819d2e6c8b6b5e8004f1744ff4bd Mon Sep 17 00:00:00 2001 From: yashnarain Date: Tue, 21 Feb 2023 16:21:29 -0500 Subject: [PATCH 14/93] major: completed reset-password functionality --- app.js | 33 ++++++++++++++++++++++++++++----- views/reset-password.ejs | 29 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 views/reset-password.ejs diff --git a/app.js b/app.js index 92635979a..fabd9774c 100644 --- a/app.js +++ b/app.js @@ -172,7 +172,8 @@ app.post("/forgotPassword", function (req, res) { console.log('Email sent: ' + info.response); } }); - res.send("Link Sent Successfuly! Check your inbox!"); + console.log("Link Sent Successfuly! Check your inbox!"); + res.redirect('/'); } else { console.log("User not found!"); res.redirect("/forgotPassword"); @@ -181,15 +182,15 @@ app.post("/forgotPassword", function (req, res) { }); }); -app.get("/reset-password/:id/:token", function (req, res) { +app.get("/reset-password/:id/:token", async function (req, res) { const { id, token } = req.params; if (id === global.resetUser.id) { - const secret = process.env.JWT_SECRET + global.resetUser.password; + const user = await User.findOne({email: global.resetUser.email}); + const secret = process.env.JWT_SECRET + user.password; try { jwt.verify(token, secret); console.log("Verified"); - //res.render("reset-password", {email: global.resetUser.email}); - res.send("Verification Successful!"); + res.render("reset-password", {email: global.resetUser.email}); } catch (error) { console.log(error); } @@ -199,6 +200,28 @@ app.get("/reset-password/:id/:token", function (req, res) { } }); +app.post("/reset-password", function (req, res) { + const update = { + password: md5(req.body.password) + }; + const filter = { + email: global.resetUser.email + } + User.findOneAndUpdate(filter, update, function(err) { + if(err) { + console.log(err) + } else { + console.log("Password Updated Successfully!"); + res.redirect("/login"); + } + }) +}); + +app.get("/logout", function(req, res) { + req.session.user = null; + res.render("home"); +}); + // GET Route for Login app.get('/login', function (req, res) { res.render("login"); diff --git a/views/reset-password.ejs b/views/reset-password.ejs new file mode 100644 index 000000000..3a92966a1 --- /dev/null +++ b/views/reset-password.ejs @@ -0,0 +1,29 @@ +<%- include('partials/header') %> + +
+

Reset your Password!

+ +
+
+
+
+ + + +
+ +
+
+ + +
+ + +
+
+
+ +
+
+ +<%- include('partials/footer') %> From 644f2e93f9c5e54e5540568e1a5c2ab0ab5a5be4 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Tue, 21 Feb 2023 17:51:26 -0500 Subject: [PATCH 15/93] major: added google sign in functionality --- app.js | 57 ++++++++++++- package-lock.json | 55 ++++++++++++ package.json | 2 + public/css/bootstrap-social.css | 147 ++++++++++++++++++++++++++++++++ views/login.ejs | 6 +- views/partials/header.ejs | 1 + views/register.ejs | 6 +- 7 files changed, 264 insertions(+), 10 deletions(-) create mode 100755 public/css/bootstrap-social.css diff --git a/app.js b/app.js index fabd9774c..959d0f671 100644 --- a/app.js +++ b/app.js @@ -8,6 +8,9 @@ const md5 = require('md5'); const session = require('express-session'); const jwt = require('jsonwebtoken'); const nodemailer = require('nodemailer'); +const passport = require("passport"); +const GoogleStrategy = require('passport-google-oauth20').Strategy; +const findOrCreate = require('mongoose-findorcreate'); const app = express(); @@ -33,6 +36,9 @@ app.use(session({ saveUninitialized: true })); +app.use(passport.initialize()); +app.use(passport.session()); + // User Schema const schema = new mongoose.Schema( { @@ -52,13 +58,17 @@ const schema = new mongoose.Schema( }, password: { type: String, - required: true, minLength: 6 + }, + googleId: { + type: String } }, { timestamps: true } ); +schema.plugin(findOrCreate); + async function validateEmail(email) { const user = await User.findOne({ email }); if (user) { @@ -73,11 +83,47 @@ async function validateEmail(email) { // Simple User Collection const User = new mongoose.model("User", schema); +passport.serializeUser(function(user, done) { + done(null, user.id); +}); + +passport.deserializeUser(function(id, done) { + User.findById(id, function(err, user) { + done(err, user); + }); +}); + +passport.use(new GoogleStrategy({ + clientID: process.env.CLIENT_ID, + clientSecret: process.env.CLIENT_SECRET, + callbackURL: "http://localhost:3000/auth/google/allpurdue", +}, +function(accessToken, refreshToken, profile, cb) { + User.findOrCreate({ googleId: profile.id, name: profile.displayName, email: profile.emails[0].value }, function (err, user) { + if(err) { + console.log(err); + } + return cb(err, user); + }); +} +)); + // GET Route for Homes app.get('/', function (req, res) { res.render("home"); }); +app.get("/auth/google", + passport.authenticate('google', { scope: ["profile", "email"] }) +); + +app.get("/auth/google/allpurdue", + passport.authenticate('google', { failureRedirect: "/login" }), + function(req, res, err) { + res.redirect("/landing"); + }); + + // GET Route for Register app.get('/register', function (req, res) { res.render("register"); @@ -85,7 +131,7 @@ app.get('/register', function (req, res) { // GET Route for Landing app.get('/landing', function (req, res) { - if (!req.session.user) { + if (req.session.user || !req.isAuthenticated()) { res.render("login"); } else { res.render("landing"); @@ -217,9 +263,12 @@ app.post("/reset-password", function (req, res) { }) }); -app.get("/logout", function(req, res) { +app.get("/logout", async function(req, res) { req.session.user = null; - res.render("home"); + req.logout(function(err) { + if (err) { return next(err); } + res.redirect('/'); + }); }); // GET Route for Login diff --git a/package-lock.json b/package-lock.json index cf9f1b95e..ea59b7528 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,11 @@ "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", + "mongoose-findorcreate": "^3.0.0", "nodemailer": "^6.9.1", "nodemon": "^2.0.20", "passport": "^0.6.0", + "passport-google-oauth20": "^2.0.0", "passport-local": "^1.0.0", "passport-local-mongoose": "^7.1.2" } @@ -1333,6 +1335,14 @@ } ] }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/bcrypt": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", @@ -2590,6 +2600,11 @@ "node": ">=4.0.0" } }, + "node_modules/mongoose-findorcreate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongoose-findorcreate/-/mongoose-findorcreate-3.0.0.tgz", + "integrity": "sha512-kQhDe5XDj6tMv8kq1wjK+hITGIGUl60rj8oGLupF9poNsqIDkAJBXudZKcCdSyBZ7p6DLK2+0jSBthrb26tSYQ==" + }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -2754,6 +2769,11 @@ "set-blocking": "^2.0.0" } }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2822,6 +2842,17 @@ "url": "https://github.com/sponsors/jaredhanson" } }, + "node_modules/passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", @@ -2846,6 +2877,25 @@ "node": ">= 8.0.0" } }, + "node_modules/passport-oauth2": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz", + "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, "node_modules/passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", @@ -3315,6 +3365,11 @@ "node": ">= 0.8" } }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index 831b6c849..120bff835 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,11 @@ "md5": "^2.3.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", + "mongoose-findorcreate": "^3.0.0", "nodemailer": "^6.9.1", "nodemon": "^2.0.20", "passport": "^0.6.0", + "passport-google-oauth20": "^2.0.0", "passport-local": "^1.0.0", "passport-local-mongoose": "^7.1.2" } diff --git a/public/css/bootstrap-social.css b/public/css/bootstrap-social.css new file mode 100755 index 000000000..93e16f766 --- /dev/null +++ b/public/css/bootstrap-social.css @@ -0,0 +1,147 @@ +/* + * Social Buttons for Bootstrap + * + * Copyright 2013-2016 Panayiotis Lipiridis + * Licensed under the MIT License + * + * https://github.com/lipis/bootstrap-social + */ + +.btn-social{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-social>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} +.btn-social.btn-lg{padding-left:61px}.btn-social.btn-lg>:first-child{line-height:45px;width:45px;font-size:1.8em} +.btn-social.btn-sm{padding-left:38px}.btn-social.btn-sm>:first-child{line-height:28px;width:28px;font-size:1.4em} +.btn-social.btn-xs{padding-left:30px}.btn-social.btn-xs>:first-child{line-height:20px;width:20px;font-size:1.2em} +.btn-social-icon{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:34px;width:34px;padding:0}.btn-social-icon>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} +.btn-social-icon.btn-lg{padding-left:61px}.btn-social-icon.btn-lg>:first-child{line-height:45px;width:45px;font-size:1.8em} +.btn-social-icon.btn-sm{padding-left:38px}.btn-social-icon.btn-sm>:first-child{line-height:28px;width:28px;font-size:1.4em} +.btn-social-icon.btn-xs{padding-left:30px}.btn-social-icon.btn-xs>:first-child{line-height:20px;width:20px;font-size:1.2em} +.btn-social-icon>:first-child{border:none;text-align:center;width:100% !important} +.btn-social-icon.btn-lg{height:45px;width:45px;padding-left:0;padding-right:0} +.btn-social-icon.btn-sm{height:30px;width:30px;padding-left:0;padding-right:0} +.btn-social-icon.btn-xs{height:22px;width:22px;padding-left:0;padding-right:0} +.btn-adn{color:#fff;background-color:#d87a68;border-color:rgba(0,0,0,0.2)}.btn-adn:focus,.btn-adn.focus{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)} +.btn-adn:hover{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)} +.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)}.btn-adn:active:hover,.btn-adn.active:hover,.open>.dropdown-toggle.btn-adn:hover,.btn-adn:active:focus,.btn-adn.active:focus,.open>.dropdown-toggle.btn-adn:focus,.btn-adn:active.focus,.btn-adn.active.focus,.open>.dropdown-toggle.btn-adn.focus{color:#fff;background-color:#b94630;border-color:rgba(0,0,0,0.2)} +.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{background-image:none} +.btn-adn.disabled:hover,.btn-adn[disabled]:hover,fieldset[disabled] .btn-adn:hover,.btn-adn.disabled:focus,.btn-adn[disabled]:focus,fieldset[disabled] .btn-adn:focus,.btn-adn.disabled.focus,.btn-adn[disabled].focus,fieldset[disabled] .btn-adn.focus{background-color:#d87a68;border-color:rgba(0,0,0,0.2)} +.btn-adn .badge{color:#d87a68;background-color:#fff} +.btn-bitbucket{color:#fff;background-color:#205081;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:focus,.btn-bitbucket.focus{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket:hover{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:active:hover,.btn-bitbucket.active:hover,.open>.dropdown-toggle.btn-bitbucket:hover,.btn-bitbucket:active:focus,.btn-bitbucket.active:focus,.open>.dropdown-toggle.btn-bitbucket:focus,.btn-bitbucket:active.focus,.btn-bitbucket.active.focus,.open>.dropdown-toggle.btn-bitbucket.focus{color:#fff;background-color:#0f253c;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{background-image:none} +.btn-bitbucket.disabled:hover,.btn-bitbucket[disabled]:hover,fieldset[disabled] .btn-bitbucket:hover,.btn-bitbucket.disabled:focus,.btn-bitbucket[disabled]:focus,fieldset[disabled] .btn-bitbucket:focus,.btn-bitbucket.disabled.focus,.btn-bitbucket[disabled].focus,fieldset[disabled] .btn-bitbucket.focus{background-color:#205081;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket .badge{color:#205081;background-color:#fff} +.btn-dropbox{color:#fff;background-color:#1087dd;border-color:rgba(0,0,0,0.2)}.btn-dropbox:focus,.btn-dropbox.focus{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)} +.btn-dropbox:hover{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)} +.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)}.btn-dropbox:active:hover,.btn-dropbox.active:hover,.open>.dropdown-toggle.btn-dropbox:hover,.btn-dropbox:active:focus,.btn-dropbox.active:focus,.open>.dropdown-toggle.btn-dropbox:focus,.btn-dropbox:active.focus,.btn-dropbox.active.focus,.open>.dropdown-toggle.btn-dropbox.focus{color:#fff;background-color:#0a568c;border-color:rgba(0,0,0,0.2)} +.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{background-image:none} +.btn-dropbox.disabled:hover,.btn-dropbox[disabled]:hover,fieldset[disabled] .btn-dropbox:hover,.btn-dropbox.disabled:focus,.btn-dropbox[disabled]:focus,fieldset[disabled] .btn-dropbox:focus,.btn-dropbox.disabled.focus,.btn-dropbox[disabled].focus,fieldset[disabled] .btn-dropbox.focus{background-color:#1087dd;border-color:rgba(0,0,0,0.2)} +.btn-dropbox .badge{color:#1087dd;background-color:#fff} +.btn-facebook{color:#fff;background-color:#3b5998;border-color:rgba(0,0,0,0.2)}.btn-facebook:focus,.btn-facebook.focus{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)} +.btn-facebook:hover{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)} +.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)}.btn-facebook:active:hover,.btn-facebook.active:hover,.open>.dropdown-toggle.btn-facebook:hover,.btn-facebook:active:focus,.btn-facebook.active:focus,.open>.dropdown-toggle.btn-facebook:focus,.btn-facebook:active.focus,.btn-facebook.active.focus,.open>.dropdown-toggle.btn-facebook.focus{color:#fff;background-color:#23345a;border-color:rgba(0,0,0,0.2)} +.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{background-image:none} +.btn-facebook.disabled:hover,.btn-facebook[disabled]:hover,fieldset[disabled] .btn-facebook:hover,.btn-facebook.disabled:focus,.btn-facebook[disabled]:focus,fieldset[disabled] .btn-facebook:focus,.btn-facebook.disabled.focus,.btn-facebook[disabled].focus,fieldset[disabled] .btn-facebook.focus{background-color:#3b5998;border-color:rgba(0,0,0,0.2)} +.btn-facebook .badge{color:#3b5998;background-color:#fff} +.btn-flickr{color:#fff;background-color:#ff0084;border-color:rgba(0,0,0,0.2)}.btn-flickr:focus,.btn-flickr.focus{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)} +.btn-flickr:hover{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)} +.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)}.btn-flickr:active:hover,.btn-flickr.active:hover,.open>.dropdown-toggle.btn-flickr:hover,.btn-flickr:active:focus,.btn-flickr.active:focus,.open>.dropdown-toggle.btn-flickr:focus,.btn-flickr:active.focus,.btn-flickr.active.focus,.open>.dropdown-toggle.btn-flickr.focus{color:#fff;background-color:#a80057;border-color:rgba(0,0,0,0.2)} +.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{background-image:none} +.btn-flickr.disabled:hover,.btn-flickr[disabled]:hover,fieldset[disabled] .btn-flickr:hover,.btn-flickr.disabled:focus,.btn-flickr[disabled]:focus,fieldset[disabled] .btn-flickr:focus,.btn-flickr.disabled.focus,.btn-flickr[disabled].focus,fieldset[disabled] .btn-flickr.focus{background-color:#ff0084;border-color:rgba(0,0,0,0.2)} +.btn-flickr .badge{color:#ff0084;background-color:#fff} +.btn-foursquare{color:#fff;background-color:#f94877;border-color:rgba(0,0,0,0.2)}.btn-foursquare:focus,.btn-foursquare.focus{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)} +.btn-foursquare:hover{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)} +.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)}.btn-foursquare:active:hover,.btn-foursquare.active:hover,.open>.dropdown-toggle.btn-foursquare:hover,.btn-foursquare:active:focus,.btn-foursquare.active:focus,.open>.dropdown-toggle.btn-foursquare:focus,.btn-foursquare:active.focus,.btn-foursquare.active.focus,.open>.dropdown-toggle.btn-foursquare.focus{color:#fff;background-color:#e30742;border-color:rgba(0,0,0,0.2)} +.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{background-image:none} +.btn-foursquare.disabled:hover,.btn-foursquare[disabled]:hover,fieldset[disabled] .btn-foursquare:hover,.btn-foursquare.disabled:focus,.btn-foursquare[disabled]:focus,fieldset[disabled] .btn-foursquare:focus,.btn-foursquare.disabled.focus,.btn-foursquare[disabled].focus,fieldset[disabled] .btn-foursquare.focus{background-color:#f94877;border-color:rgba(0,0,0,0.2)} +.btn-foursquare .badge{color:#f94877;background-color:#fff} +.btn-github{color:#fff;background-color:#444;border-color:rgba(0,0,0,0.2)}.btn-github:focus,.btn-github.focus{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)} +.btn-github:hover{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)} +.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)}.btn-github:active:hover,.btn-github.active:hover,.open>.dropdown-toggle.btn-github:hover,.btn-github:active:focus,.btn-github.active:focus,.open>.dropdown-toggle.btn-github:focus,.btn-github:active.focus,.btn-github.active.focus,.open>.dropdown-toggle.btn-github.focus{color:#fff;background-color:#191919;border-color:rgba(0,0,0,0.2)} +.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{background-image:none} +.btn-github.disabled:hover,.btn-github[disabled]:hover,fieldset[disabled] .btn-github:hover,.btn-github.disabled:focus,.btn-github[disabled]:focus,fieldset[disabled] .btn-github:focus,.btn-github.disabled.focus,.btn-github[disabled].focus,fieldset[disabled] .btn-github.focus{background-color:#444;border-color:rgba(0,0,0,0.2)} +.btn-github .badge{color:#444;background-color:#fff} +.btn-google{color:#fff;background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}.btn-google:focus,.btn-google.focus{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)} +.btn-google:hover{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)} +.btn-google:active,.btn-google.active,.open>.dropdown-toggle.btn-google{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)}.btn-google:active:hover,.btn-google.active:hover,.open>.dropdown-toggle.btn-google:hover,.btn-google:active:focus,.btn-google.active:focus,.open>.dropdown-toggle.btn-google:focus,.btn-google:active.focus,.btn-google.active.focus,.open>.dropdown-toggle.btn-google.focus{color:#fff;background-color:#a32b1c;border-color:rgba(0,0,0,0.2)} +.btn-google:active,.btn-google.active,.open>.dropdown-toggle.btn-google{background-image:none} +.btn-google.disabled:hover,.btn-google[disabled]:hover,fieldset[disabled] .btn-google:hover,.btn-google.disabled:focus,.btn-google[disabled]:focus,fieldset[disabled] .btn-google:focus,.btn-google.disabled.focus,.btn-google[disabled].focus,fieldset[disabled] .btn-google.focus{background-color:#dd4b39;border-color:rgba(0,0,0,0.2)} +.btn-google .badge{color:#dd4b39;background-color:#fff} +.btn-instagram{color:#fff;background-color:#3f729b;border-color:rgba(0,0,0,0.2)}.btn-instagram:focus,.btn-instagram.focus{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)} +.btn-instagram:hover{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)} +.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)}.btn-instagram:active:hover,.btn-instagram.active:hover,.open>.dropdown-toggle.btn-instagram:hover,.btn-instagram:active:focus,.btn-instagram.active:focus,.open>.dropdown-toggle.btn-instagram:focus,.btn-instagram:active.focus,.btn-instagram.active.focus,.open>.dropdown-toggle.btn-instagram.focus{color:#fff;background-color:#26455d;border-color:rgba(0,0,0,0.2)} +.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{background-image:none} +.btn-instagram.disabled:hover,.btn-instagram[disabled]:hover,fieldset[disabled] .btn-instagram:hover,.btn-instagram.disabled:focus,.btn-instagram[disabled]:focus,fieldset[disabled] .btn-instagram:focus,.btn-instagram.disabled.focus,.btn-instagram[disabled].focus,fieldset[disabled] .btn-instagram.focus{background-color:#3f729b;border-color:rgba(0,0,0,0.2)} +.btn-instagram .badge{color:#3f729b;background-color:#fff} +.btn-linkedin{color:#fff;background-color:#007bb6;border-color:rgba(0,0,0,0.2)}.btn-linkedin:focus,.btn-linkedin.focus{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)} +.btn-linkedin:hover{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)} +.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)}.btn-linkedin:active:hover,.btn-linkedin.active:hover,.open>.dropdown-toggle.btn-linkedin:hover,.btn-linkedin:active:focus,.btn-linkedin.active:focus,.open>.dropdown-toggle.btn-linkedin:focus,.btn-linkedin:active.focus,.btn-linkedin.active.focus,.open>.dropdown-toggle.btn-linkedin.focus{color:#fff;background-color:#00405f;border-color:rgba(0,0,0,0.2)} +.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{background-image:none} +.btn-linkedin.disabled:hover,.btn-linkedin[disabled]:hover,fieldset[disabled] .btn-linkedin:hover,.btn-linkedin.disabled:focus,.btn-linkedin[disabled]:focus,fieldset[disabled] .btn-linkedin:focus,.btn-linkedin.disabled.focus,.btn-linkedin[disabled].focus,fieldset[disabled] .btn-linkedin.focus{background-color:#007bb6;border-color:rgba(0,0,0,0.2)} +.btn-linkedin .badge{color:#007bb6;background-color:#fff} +.btn-microsoft{color:#fff;background-color:#2672ec;border-color:rgba(0,0,0,0.2)}.btn-microsoft:focus,.btn-microsoft.focus{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)} +.btn-microsoft:hover{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)} +.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)}.btn-microsoft:active:hover,.btn-microsoft.active:hover,.open>.dropdown-toggle.btn-microsoft:hover,.btn-microsoft:active:focus,.btn-microsoft.active:focus,.open>.dropdown-toggle.btn-microsoft:focus,.btn-microsoft:active.focus,.btn-microsoft.active.focus,.open>.dropdown-toggle.btn-microsoft.focus{color:#fff;background-color:#0f4bac;border-color:rgba(0,0,0,0.2)} +.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{background-image:none} +.btn-microsoft.disabled:hover,.btn-microsoft[disabled]:hover,fieldset[disabled] .btn-microsoft:hover,.btn-microsoft.disabled:focus,.btn-microsoft[disabled]:focus,fieldset[disabled] .btn-microsoft:focus,.btn-microsoft.disabled.focus,.btn-microsoft[disabled].focus,fieldset[disabled] .btn-microsoft.focus{background-color:#2672ec;border-color:rgba(0,0,0,0.2)} +.btn-microsoft .badge{color:#2672ec;background-color:#fff} +.btn-odnoklassniki{color:#fff;background-color:#f4731c;border-color:rgba(0,0,0,0.2)}.btn-odnoklassniki:focus,.btn-odnoklassniki.focus{color:#fff;background-color:#d35b0a;border-color:rgba(0,0,0,0.2)} +.btn-odnoklassniki:hover{color:#fff;background-color:#d35b0a;border-color:rgba(0,0,0,0.2)} +.btn-odnoklassniki:active,.btn-odnoklassniki.active,.open>.dropdown-toggle.btn-odnoklassniki{color:#fff;background-color:#d35b0a;border-color:rgba(0,0,0,0.2)}.btn-odnoklassniki:active:hover,.btn-odnoklassniki.active:hover,.open>.dropdown-toggle.btn-odnoklassniki:hover,.btn-odnoklassniki:active:focus,.btn-odnoklassniki.active:focus,.open>.dropdown-toggle.btn-odnoklassniki:focus,.btn-odnoklassniki:active.focus,.btn-odnoklassniki.active.focus,.open>.dropdown-toggle.btn-odnoklassniki.focus{color:#fff;background-color:#b14c09;border-color:rgba(0,0,0,0.2)} +.btn-odnoklassniki:active,.btn-odnoklassniki.active,.open>.dropdown-toggle.btn-odnoklassniki{background-image:none} +.btn-odnoklassniki.disabled:hover,.btn-odnoklassniki[disabled]:hover,fieldset[disabled] .btn-odnoklassniki:hover,.btn-odnoklassniki.disabled:focus,.btn-odnoklassniki[disabled]:focus,fieldset[disabled] .btn-odnoklassniki:focus,.btn-odnoklassniki.disabled.focus,.btn-odnoklassniki[disabled].focus,fieldset[disabled] .btn-odnoklassniki.focus{background-color:#f4731c;border-color:rgba(0,0,0,0.2)} +.btn-odnoklassniki .badge{color:#f4731c;background-color:#fff} +.btn-openid{color:#fff;background-color:#f7931e;border-color:rgba(0,0,0,0.2)}.btn-openid:focus,.btn-openid.focus{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)} +.btn-openid:hover{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)} +.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)}.btn-openid:active:hover,.btn-openid.active:hover,.open>.dropdown-toggle.btn-openid:hover,.btn-openid:active:focus,.btn-openid.active:focus,.open>.dropdown-toggle.btn-openid:focus,.btn-openid:active.focus,.btn-openid.active.focus,.open>.dropdown-toggle.btn-openid.focus{color:#fff;background-color:#b86607;border-color:rgba(0,0,0,0.2)} +.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{background-image:none} +.btn-openid.disabled:hover,.btn-openid[disabled]:hover,fieldset[disabled] .btn-openid:hover,.btn-openid.disabled:focus,.btn-openid[disabled]:focus,fieldset[disabled] .btn-openid:focus,.btn-openid.disabled.focus,.btn-openid[disabled].focus,fieldset[disabled] .btn-openid.focus{background-color:#f7931e;border-color:rgba(0,0,0,0.2)} +.btn-openid .badge{color:#f7931e;background-color:#fff} +.btn-pinterest{color:#fff;background-color:#cb2027;border-color:rgba(0,0,0,0.2)}.btn-pinterest:focus,.btn-pinterest.focus{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)} +.btn-pinterest:hover{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)} +.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)}.btn-pinterest:active:hover,.btn-pinterest.active:hover,.open>.dropdown-toggle.btn-pinterest:hover,.btn-pinterest:active:focus,.btn-pinterest.active:focus,.open>.dropdown-toggle.btn-pinterest:focus,.btn-pinterest:active.focus,.btn-pinterest.active.focus,.open>.dropdown-toggle.btn-pinterest.focus{color:#fff;background-color:#801419;border-color:rgba(0,0,0,0.2)} +.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{background-image:none} +.btn-pinterest.disabled:hover,.btn-pinterest[disabled]:hover,fieldset[disabled] .btn-pinterest:hover,.btn-pinterest.disabled:focus,.btn-pinterest[disabled]:focus,fieldset[disabled] .btn-pinterest:focus,.btn-pinterest.disabled.focus,.btn-pinterest[disabled].focus,fieldset[disabled] .btn-pinterest.focus{background-color:#cb2027;border-color:rgba(0,0,0,0.2)} +.btn-pinterest .badge{color:#cb2027;background-color:#fff} +.btn-reddit{color:#000;background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}.btn-reddit:focus,.btn-reddit.focus{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)} +.btn-reddit:hover{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)} +.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)}.btn-reddit:active:hover,.btn-reddit.active:hover,.open>.dropdown-toggle.btn-reddit:hover,.btn-reddit:active:focus,.btn-reddit.active:focus,.open>.dropdown-toggle.btn-reddit:focus,.btn-reddit:active.focus,.btn-reddit.active.focus,.open>.dropdown-toggle.btn-reddit.focus{color:#000;background-color:#98ccff;border-color:rgba(0,0,0,0.2)} +.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{background-image:none} +.btn-reddit.disabled:hover,.btn-reddit[disabled]:hover,fieldset[disabled] .btn-reddit:hover,.btn-reddit.disabled:focus,.btn-reddit[disabled]:focus,fieldset[disabled] .btn-reddit:focus,.btn-reddit.disabled.focus,.btn-reddit[disabled].focus,fieldset[disabled] .btn-reddit.focus{background-color:#eff7ff;border-color:rgba(0,0,0,0.2)} +.btn-reddit .badge{color:#eff7ff;background-color:#000} +.btn-soundcloud{color:#fff;background-color:#f50;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:focus,.btn-soundcloud.focus{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud:hover{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:active:hover,.btn-soundcloud.active:hover,.open>.dropdown-toggle.btn-soundcloud:hover,.btn-soundcloud:active:focus,.btn-soundcloud.active:focus,.open>.dropdown-toggle.btn-soundcloud:focus,.btn-soundcloud:active.focus,.btn-soundcloud.active.focus,.open>.dropdown-toggle.btn-soundcloud.focus{color:#fff;background-color:#a83800;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{background-image:none} +.btn-soundcloud.disabled:hover,.btn-soundcloud[disabled]:hover,fieldset[disabled] .btn-soundcloud:hover,.btn-soundcloud.disabled:focus,.btn-soundcloud[disabled]:focus,fieldset[disabled] .btn-soundcloud:focus,.btn-soundcloud.disabled.focus,.btn-soundcloud[disabled].focus,fieldset[disabled] .btn-soundcloud.focus{background-color:#f50;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud .badge{color:#f50;background-color:#fff} +.btn-tumblr{color:#fff;background-color:#2c4762;border-color:rgba(0,0,0,0.2)}.btn-tumblr:focus,.btn-tumblr.focus{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)} +.btn-tumblr:hover{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)} +.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)}.btn-tumblr:active:hover,.btn-tumblr.active:hover,.open>.dropdown-toggle.btn-tumblr:hover,.btn-tumblr:active:focus,.btn-tumblr.active:focus,.open>.dropdown-toggle.btn-tumblr:focus,.btn-tumblr:active.focus,.btn-tumblr.active.focus,.open>.dropdown-toggle.btn-tumblr.focus{color:#fff;background-color:#111c26;border-color:rgba(0,0,0,0.2)} +.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{background-image:none} +.btn-tumblr.disabled:hover,.btn-tumblr[disabled]:hover,fieldset[disabled] .btn-tumblr:hover,.btn-tumblr.disabled:focus,.btn-tumblr[disabled]:focus,fieldset[disabled] .btn-tumblr:focus,.btn-tumblr.disabled.focus,.btn-tumblr[disabled].focus,fieldset[disabled] .btn-tumblr.focus{background-color:#2c4762;border-color:rgba(0,0,0,0.2)} +.btn-tumblr .badge{color:#2c4762;background-color:#fff} +.btn-twitter{color:#fff;background-color:#55acee;border-color:rgba(0,0,0,0.2)}.btn-twitter:focus,.btn-twitter.focus{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)} +.btn-twitter:hover{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)} +.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)}.btn-twitter:active:hover,.btn-twitter.active:hover,.open>.dropdown-toggle.btn-twitter:hover,.btn-twitter:active:focus,.btn-twitter.active:focus,.open>.dropdown-toggle.btn-twitter:focus,.btn-twitter:active.focus,.btn-twitter.active.focus,.open>.dropdown-toggle.btn-twitter.focus{color:#fff;background-color:#1583d7;border-color:rgba(0,0,0,0.2)} +.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{background-image:none} +.btn-twitter.disabled:hover,.btn-twitter[disabled]:hover,fieldset[disabled] .btn-twitter:hover,.btn-twitter.disabled:focus,.btn-twitter[disabled]:focus,fieldset[disabled] .btn-twitter:focus,.btn-twitter.disabled.focus,.btn-twitter[disabled].focus,fieldset[disabled] .btn-twitter.focus{background-color:#55acee;border-color:rgba(0,0,0,0.2)} +.btn-twitter .badge{color:#55acee;background-color:#fff} +.btn-vimeo{color:#fff;background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}.btn-vimeo:focus,.btn-vimeo.focus{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)} +.btn-vimeo:hover{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)} +.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)}.btn-vimeo:active:hover,.btn-vimeo.active:hover,.open>.dropdown-toggle.btn-vimeo:hover,.btn-vimeo:active:focus,.btn-vimeo.active:focus,.open>.dropdown-toggle.btn-vimeo:focus,.btn-vimeo:active.focus,.btn-vimeo.active.focus,.open>.dropdown-toggle.btn-vimeo.focus{color:#fff;background-color:#0f7b9f;border-color:rgba(0,0,0,0.2)} +.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{background-image:none} +.btn-vimeo.disabled:hover,.btn-vimeo[disabled]:hover,fieldset[disabled] .btn-vimeo:hover,.btn-vimeo.disabled:focus,.btn-vimeo[disabled]:focus,fieldset[disabled] .btn-vimeo:focus,.btn-vimeo.disabled.focus,.btn-vimeo[disabled].focus,fieldset[disabled] .btn-vimeo.focus{background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)} +.btn-vimeo .badge{color:#1ab7ea;background-color:#fff} +.btn-vk{color:#fff;background-color:#587ea3;border-color:rgba(0,0,0,0.2)}.btn-vk:focus,.btn-vk.focus{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)} +.btn-vk:hover{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)} +.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)}.btn-vk:active:hover,.btn-vk.active:hover,.open>.dropdown-toggle.btn-vk:hover,.btn-vk:active:focus,.btn-vk.active:focus,.open>.dropdown-toggle.btn-vk:focus,.btn-vk:active.focus,.btn-vk.active.focus,.open>.dropdown-toggle.btn-vk.focus{color:#fff;background-color:#3a526b;border-color:rgba(0,0,0,0.2)} +.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{background-image:none} +.btn-vk.disabled:hover,.btn-vk[disabled]:hover,fieldset[disabled] .btn-vk:hover,.btn-vk.disabled:focus,.btn-vk[disabled]:focus,fieldset[disabled] .btn-vk:focus,.btn-vk.disabled.focus,.btn-vk[disabled].focus,fieldset[disabled] .btn-vk.focus{background-color:#587ea3;border-color:rgba(0,0,0,0.2)} +.btn-vk .badge{color:#587ea3;background-color:#fff} +.btn-yahoo{color:#fff;background-color:#720e9e;border-color:rgba(0,0,0,0.2)}.btn-yahoo:focus,.btn-yahoo.focus{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)} +.btn-yahoo:hover{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)} +.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)}.btn-yahoo:active:hover,.btn-yahoo.active:hover,.open>.dropdown-toggle.btn-yahoo:hover,.btn-yahoo:active:focus,.btn-yahoo.active:focus,.open>.dropdown-toggle.btn-yahoo:focus,.btn-yahoo:active.focus,.btn-yahoo.active.focus,.open>.dropdown-toggle.btn-yahoo.focus{color:#fff;background-color:#39074e;border-color:rgba(0,0,0,0.2)} +.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{background-image:none} +.btn-yahoo.disabled:hover,.btn-yahoo[disabled]:hover,fieldset[disabled] .btn-yahoo:hover,.btn-yahoo.disabled:focus,.btn-yahoo[disabled]:focus,fieldset[disabled] .btn-yahoo:focus,.btn-yahoo.disabled.focus,.btn-yahoo[disabled].focus,fieldset[disabled] .btn-yahoo.focus{background-color:#720e9e;border-color:rgba(0,0,0,0.2)} +.btn-yahoo .badge{color:#720e9e;background-color:#fff} diff --git a/views/login.ejs b/views/login.ejs index a3ffd53f6..24ebbb56a 100644 --- a/views/login.ejs +++ b/views/login.ejs @@ -30,16 +30,16 @@
- +
diff --git a/views/partials/header.ejs b/views/partials/header.ejs index 4eb7d90a5..d8be374ea 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -7,6 +7,7 @@ + diff --git a/views/register.ejs b/views/register.ejs index f592f1c28..c01c984fc 100644 --- a/views/register.ejs +++ b/views/register.ejs @@ -28,16 +28,16 @@ - + From 45b4150cdef80861e3d8d2096bf994b97577b0e5 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Tue, 21 Feb 2023 20:14:27 -0500 Subject: [PATCH 16/93] minor: fixed login bug --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 959d0f671..4fa1659d5 100644 --- a/app.js +++ b/app.js @@ -131,7 +131,7 @@ app.get('/register', function (req, res) { // GET Route for Landing app.get('/landing', function (req, res) { - if (req.session.user || !req.isAuthenticated()) { + if (!req.session.user && !req.isAuthenticated()) { res.render("login"); } else { res.render("landing"); From 1bec7abd6315d4eee04d5258b3d11cd7ebb7a4d2 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Tue, 21 Feb 2023 20:21:43 -0500 Subject: [PATCH 17/93] minor: fixed password length bug --- app.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app.js b/app.js index 4fa1659d5..37fd61be6 100644 --- a/app.js +++ b/app.js @@ -140,6 +140,10 @@ app.get('/landing', function (req, res) { // POST Route for Register app.post('/register', function (req, res) { + if(req.body.password.length < 6) { + console.log("Password length is less than 6!"); + return res.redirect('/register'); + } const newUser = new User({ name: req.body.name, email: req.body.username, From 7ad47eab28550f87ca417531b8267fdfe3ce3be3 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Tue, 21 Feb 2023 20:51:40 -0500 Subject: [PATCH 18/93] minor: added login check --- app.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 37fd61be6..a4f6bea83 100644 --- a/app.js +++ b/app.js @@ -176,8 +176,11 @@ app.post('/login', function (req, res) { res.redirect("/landing"); } else { console.log("Incorrect Password!"); - res.redirect("login"); + res.redirect("/login"); } + } else { + console.log("User not found!"); + res.redirect("/login"); } } } From 73ac43c308541282783f4e17a873b89ab83c8415 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Tue, 21 Feb 2023 21:29:50 -0500 Subject: [PATCH 19/93] minor: removed password length --- app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app.js b/app.js index a4f6bea83..193b0b764 100644 --- a/app.js +++ b/app.js @@ -58,7 +58,6 @@ const schema = new mongoose.Schema( }, password: { type: String, - minLength: 6 }, googleId: { type: String From 85aead18c597e98e0ddefd6d559e2b36ccd773bd Mon Sep 17 00:00:00 2001 From: Antony Date: Tue, 21 Feb 2023 21:39:43 -0500 Subject: [PATCH 20/93] Cors --- app.js | 13 ++++++++++++- package-lock.json | 13 +++++++++++++ package.json | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index a4f6bea83..7267795d0 100644 --- a/app.js +++ b/app.js @@ -14,8 +14,17 @@ const findOrCreate = require('mongoose-findorcreate'); const app = express(); +const cors=require("cors"); +const corsOptions ={ + origin:'*', + credentials:true, + optionSuccessStatus:200, +} + +app.use(cors(corsOptions)); + mongoose.set('strictQuery', false); -mongoose.connect("mongodb://localhost:27017/allPurdueDB"); +mongoose.connect("mongodb://127.0.0.1:27017/allPurdueDB"); const transporter = nodemailer.createTransport({ service: 'gmail', host: 'smtp.gmail.com', @@ -30,6 +39,7 @@ const transporter = nodemailer.createTransport({ app.use(express.static("public")); app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.json()); app.use(session({ secret: process.env.SESSION_SECRET, resave: false, @@ -140,6 +150,7 @@ app.get('/landing', function (req, res) { // POST Route for Register app.post('/register', function (req, res) { + console.log(req.body); if(req.body.password.length < 6) { console.log("Password length is less than 6!"); return res.redirect('/register'); diff --git a/package-lock.json b/package-lock.json index ea59b7528..1c670d1a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@sendgrid/mail": "^7.7.0", "bcrypt": "^5.1.0", + "cors": "^2.8.5", "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", @@ -1627,6 +1628,18 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", diff --git a/package.json b/package.json index 120bff835..85e69b8a3 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "@sendgrid/mail": "^7.7.0", "bcrypt": "^5.1.0", + "cors": "^2.8.5", "dotenv": "^16.0.3", "ejs": "^3.1.8", "express": "^4.18.2", From 2c568e3cb0cbd9aff155708432ba2e135ff847ef Mon Sep 17 00:00:00 2001 From: Pramey Kabra Date: Wed, 22 Feb 2023 23:44:39 -0500 Subject: [PATCH 21/93] Major: Add views and routes for adding places, view all places and indiv place --- app.js | 213 ++++++++++++++++++++++++++++++++++++++-- views/add_place.ejs | 29 ++++++ views/place-details.ejs | 15 +++ views/places.ejs | 24 +++++ 4 files changed, 275 insertions(+), 6 deletions(-) create mode 100644 views/add_place.ejs create mode 100644 views/place-details.ejs create mode 100644 views/places.ejs diff --git a/app.js b/app.js index 679f45f8b..97051eebf 100644 --- a/app.js +++ b/app.js @@ -24,7 +24,7 @@ const corsOptions ={ app.use(cors(corsOptions)); mongoose.set('strictQuery', false); -mongoose.connect("mongodb://127.0.0.1:27017/allPurdueDB"); +mongoose.connect("mongodb://localhost:27017/allPurdueDB"); const transporter = nodemailer.createTransport({ service: 'gmail', host: 'smtp.gmail.com', @@ -49,8 +49,12 @@ app.use(session({ app.use(passport.initialize()); app.use(passport.session()); +/* ---------- [Start] Models ---------- */ + +const Schema = mongoose.Schema; + // User Schema -const schema = new mongoose.Schema( +const userSchema = new Schema( { name: { type: String, @@ -69,6 +73,10 @@ const schema = new mongoose.Schema( password: { type: String, }, + postedReviews: [{ + type: Schema.Types.ObjectId, + ref: 'Review', + }], googleId: { type: String } @@ -76,7 +84,7 @@ const schema = new mongoose.Schema( { timestamps: true } ); -schema.plugin(findOrCreate); +userSchema.plugin(findOrCreate); async function validateEmail(email) { const user = await User.findOne({ email }); @@ -90,7 +98,100 @@ async function validateEmail(email) { } // Simple User Collection -const User = new mongoose.model("User", schema); +const User = new mongoose.model("User", userSchema); + +// Place Schema + +const placeSchema = new Schema( + { + name: { + type: String, + required: true, + }, + description: { + type: String, + required: true, + }, + placeType: { + type: String, + required: true, + }, + tags: [ + { + type: String, + }, + ], + location: { + // Reference - https://mongoosejs.com/docs/geojson.html + type: { + type: String, + enum: ["Point"], + required: true, + }, + coordinates: { + type: [Number], + required: true, + }, + }, + reviews: [{ + type: Schema.Types.ObjectId, + ref: 'Review', + }] + // TODO: Ratings, Average Rating and Reviews, and Similar Places (i think that is a FE issue) + }, + { timestamps: true } +); + +const Place = new mongoose.model("Place", placeSchema); + +// Anpther virtual to find number of ratings for each place +// Usage example - +// const doc = await Band.findOne({ name: 'Motley Crue' }).populate('numMembers'); +// doc.numMembers; // 2 + +placeSchema.virtual('numRatings', { + ref: 'Review', + localField: 'name', + foreignField: 'place', + count: true +}) + +// Reviews Schema + +const reviewSchema = new Schema( + { + rating: { + type: Number, + minimum: [1, "Minimum rating of 1 is required"], + maximum: [5, "Maximum rating of 5 is required"], + required: true, + }, + review: { + type: String, + }, + place: { + type: Schema.Types.ObjectId, + ref: 'Place', + required: true, + }, + postedBy: { + type: Schema.Types.ObjectId, + ref: 'User', + required: true, + }, + postLikeUsersList : [{ + type: Schema.Types.ObjectId, + ref: 'User', + }] + }, + { timestamps: true } + ); + +const Review = new mongoose.model("Review", reviewSchema); + +/* ---------- [End] Models ---------- */ + +/* ---------- [Start] Google Auth ---------- */ passport.serializeUser(function(user, done) { done(null, user.id); @@ -117,6 +218,105 @@ function(accessToken, refreshToken, profile, cb) { } )); +/* ---------- [End] Google Auth ---------- */ + + +/* ---------- [Start] Place Routes ---------- */ + +// // for getting a place +// app.get('/:place_id', (req, res) => { +// Place.findById(req.params.id) +// .then((place) => res.json(place)) +// .catch((err) => console.log(err)); +// }); + +app.get('/add_place', (req, res) => { + res.render("add_place"); +}); + +// for adding a place +app.post('/add_place', async (req, res) => { + try { + const { name, description, placeType, latitude, longitude } = req.body; + + // Create a new Place object + const place = new Place({ + name, + description, + placeType, + location: { + type: 'Point', + coordinates: [latitude, longitude], + }, + }); + + // Save the Place object to the database + await place.save(); + res.render('landing') + + } catch (err) { + console.error(err); + res.status(500).send('Error adding place'); + } +}); + +// GET route for displaying all places +app.get('/places', (req, res) => { + // Use Mongoose to retrieve all places from the database + Place.find({}, (err, places) => { + if (err) { + console.log(err); + res.redirect('/'); + } else { + res.render('places', { places: places }); + } + }); +}); + +// GET route for displaying a single place by ID +app.get('/places/:id', (req, res) => { + // Use Mongoose to retrieve a single place by its ID from the database + Place.findById(req.params.id).populate('reviews').exec((err, place) => { + if (err) { + console.log(err); + res.redirect('/'); + } else { + res.render('place-details', { place: place }); + } + }); +}); + +// // for modifying a place +// app.post('/modify/:place_id', (req, res) => { +// Place.findById(req.params.id) +// .then((place) =>{ +// place.name = req.body.name; +// place.description = req.body.description; +// place.placeType = req.body.placeType; +// place.tags = req.body.tags; +// place.location = req.body.location; +// newPlace.save() +// .then(() => res.json('Place Modified')) +// .catch((err) => console.log(err)); +// }) +// .catch((err) => console.log(err)); +// }); + +// // for removing a place +// app.delete('/:place_id', (req, res) => { +// Place.findByIdAndDelete(req.params.id, (err) => { +// if (err) { +// console.log(err); +// } else { +// res.render("landing"); +// } +// }); +// }); + +/* ---------- [End] Place Routes ---------- */ + +/* ---------- [Start] Login/Register/Home Routes ---------- */ + // GET Route for Homes app.get('/', function (req, res) { res.render("home"); @@ -132,7 +332,6 @@ app.get("/auth/google/allpurdue", res.redirect("/landing"); }); - // GET Route for Register app.get('/register', function (req, res) { res.render("register"); @@ -300,4 +499,6 @@ app.get('/landing', function (req, res) { app.listen(3000, function () { console.log("Server started at Port 3000!"); -}); \ No newline at end of file +}); + +/* ---------- [End] Login/Register/Home Routes ---------- */ \ No newline at end of file diff --git a/views/add_place.ejs b/views/add_place.ejs new file mode 100644 index 000000000..78af8affe --- /dev/null +++ b/views/add_place.ejs @@ -0,0 +1,29 @@ + + + + + Add New Place + + +

Add New Place

+
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + diff --git a/views/place-details.ejs b/views/place-details.ejs new file mode 100644 index 000000000..67bbc76d4 --- /dev/null +++ b/views/place-details.ejs @@ -0,0 +1,15 @@ +

<%= place.name %>

+

<%= place.description %>

+

<%= place.placeType %>

+ + + +

Reviews

+
    + <% place.reviews.forEach(function(review) { %> +
  • +

    <%= review.rating %> stars

    +

    <%= review.content %>

    +
  • + <% }); %> +
diff --git a/views/places.ejs b/views/places.ejs new file mode 100644 index 000000000..95e004d68 --- /dev/null +++ b/views/places.ejs @@ -0,0 +1,24 @@ + + + + + All Places + + +

All Places

+
    + <% places.forEach(function(place) { %> +
  • +

    <%= place.name %>

    +

    <%= place.description %>

    +

    Type: <%= place.placeType %>

    + <% if (place.tags.length > 0) { %> +

    Tags: <%= place.tags.join(', ') %>

    + <% } %> +

    Location: <%= place.location.coordinates[1] %>, <%= place.location.coordinates[0] %>

    +

    View

    +
  • + <% }); %> +
+ + From 07e0115a6a31907ec06add226324985f662e75ec Mon Sep 17 00:00:00 2001 From: Pramey Kabra Date: Thu, 23 Feb 2023 16:27:34 -0500 Subject: [PATCH 22/93] Minor changes --- app.js | 26 ++++++++++++++++++-------- views/{places.ejs => all_places.ejs} | 0 views/place-details.ejs | 6 +++++- 3 files changed, 23 insertions(+), 9 deletions(-) rename views/{places.ejs => all_places.ejs} (100%) diff --git a/app.js b/app.js index 97051eebf..832f293b7 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,7 @@ const findOrCreate = require('mongoose-findorcreate'); const app = express(); const cors=require("cors"); +const { Router } = require('express'); const corsOptions ={ origin:'*', credentials:true, @@ -223,13 +224,6 @@ function(accessToken, refreshToken, profile, cb) { /* ---------- [Start] Place Routes ---------- */ -// // for getting a place -// app.get('/:place_id', (req, res) => { -// Place.findById(req.params.id) -// .then((place) => res.json(place)) -// .catch((err) => console.log(err)); -// }); - app.get('/add_place', (req, res) => { res.render("add_place"); }); @@ -268,7 +262,7 @@ app.get('/places', (req, res) => { console.log(err); res.redirect('/'); } else { - res.render('places', { places: places }); + res.render('all_places', { places: places }); } }); }); @@ -286,6 +280,18 @@ app.get('/places/:id', (req, res) => { }); }); +// // Add average rating functionality +// app.get('/places/:id', async (req, res) => { +// try { +// const place = await Place.findById(req.params.id).populate('reviews'); +// const reviewRatings = place.reviews.map(review => review.rating); +// const averageRating = reviewRatings.reduce((acc, curr) => acc + curr, 0) / reviewRatings.length; +// res.render('place_details', { place, averageRating }); +// } catch (error) { +// console.error(error); +// } +// }); + // // for modifying a place // app.post('/modify/:place_id', (req, res) => { // Place.findById(req.params.id) @@ -315,6 +321,10 @@ app.get('/places/:id', (req, res) => { /* ---------- [End] Place Routes ---------- */ +/* ---------- [Start] Ratings Routes ---------- */ + +/* ---------- [End] Ratings Routes ---------- */ + /* ---------- [Start] Login/Register/Home Routes ---------- */ // GET Route for Homes diff --git a/views/places.ejs b/views/all_places.ejs similarity index 100% rename from views/places.ejs rename to views/all_places.ejs diff --git a/views/place-details.ejs b/views/place-details.ejs index 67bbc76d4..aee5d7eed 100644 --- a/views/place-details.ejs +++ b/views/place-details.ejs @@ -2,9 +2,13 @@

<%= place.description %>

<%= place.placeType %>

+ +

Location:

+

<%= place.name %> on Google Maps

-

Reviews

+

Reviews

    <% place.reviews.forEach(function(review) { %>
  • From a41e8b72fae58be2b4c259b4183f0546d441b338 Mon Sep 17 00:00:00 2001 From: Pramey Kabra Date: Thu, 23 Feb 2023 18:12:12 -0500 Subject: [PATCH 23/93] Major: Add average and num rating functionality + Minor changes Test OK Functionality working - Login, Logout, Forgot/Reset Password, Google Login, All Places, Indiv Places, Average and Number Ratings, Reviews display, Location (google maps) --- app.js | 94 ++++++++++++++++++----------------------- views/all_places.ejs | 4 +- views/home.ejs | 1 + views/place-details.ejs | 11 +++-- 4 files changed, 53 insertions(+), 57 deletions(-) diff --git a/app.js b/app.js index 832f293b7..45e350684 100644 --- a/app.js +++ b/app.js @@ -98,7 +98,6 @@ async function validateEmail(email) { return true; } -// Simple User Collection const User = new mongoose.model("User", userSchema); // Place Schema @@ -138,7 +137,6 @@ const placeSchema = new Schema( type: Schema.Types.ObjectId, ref: 'Review', }] - // TODO: Ratings, Average Rating and Reviews, and Similar Places (i think that is a FE issue) }, { timestamps: true } ); @@ -150,12 +148,12 @@ const Place = new mongoose.model("Place", placeSchema); // const doc = await Band.findOne({ name: 'Motley Crue' }).populate('numMembers'); // doc.numMembers; // 2 -placeSchema.virtual('numRatings', { - ref: 'Review', - localField: 'name', - foreignField: 'place', - count: true -}) +// placeSchema.virtual('numRatings', { +// ref: 'Review', +// localField: 'name', +// foreignField: 'place', +// count: true +// }) // Reviews Schema @@ -167,7 +165,7 @@ const reviewSchema = new Schema( maximum: [5, "Maximum rating of 5 is required"], required: true, }, - review: { + text: { type: String, }, place: { @@ -175,15 +173,15 @@ const reviewSchema = new Schema( ref: 'Place', required: true, }, - postedBy: { + author: { type: Schema.Types.ObjectId, ref: 'User', required: true, }, - postLikeUsersList : [{ - type: Schema.Types.ObjectId, - ref: 'User', - }] + // postLikeUsersList : [{ + // type: Schema.Types.ObjectId, + // ref: 'User', + // }] }, { timestamps: true } ); @@ -255,43 +253,39 @@ app.post('/add_place', async (req, res) => { }); // GET route for displaying all places -app.get('/places', (req, res) => { - // Use Mongoose to retrieve all places from the database - Place.find({}, (err, places) => { - if (err) { - console.log(err); - res.redirect('/'); - } else { - res.render('all_places', { places: places }); - } - }); +app.get('/places', async (req, res) => { + try { + const places = await Place.find({}); + const placesWithAvgRating = await Promise.all(places.map(async (place) => { + // Add average rating functionality + const reviews = await Review.find({ place: place._id }); + const totalRatings = reviews.reduce((acc, review) => acc + review.rating, 0); + const numReviews = reviews.length > 0 ? reviews.length : 0; + const avgRating = reviews.length > 0 ? totalRatings / reviews.length : 0; + return { ...place._doc, avgRating, numReviews }; + })); + res.render('all_places', { places: placesWithAvgRating }); + } catch (error) { + console.error(error); + res.status(500).send('Internal Server Error'); + } }); + // GET route for displaying a single place by ID -app.get('/places/:id', (req, res) => { - // Use Mongoose to retrieve a single place by its ID from the database - Place.findById(req.params.id).populate('reviews').exec((err, place) => { - if (err) { - console.log(err); - res.redirect('/'); - } else { - res.render('place-details', { place: place }); - } - }); +app.get('/places/:id', async (req, res) => { + try { + const place = await Place.findById(req.params.id).populate('reviews'); + // Add average rating functionality + const reviewRatings = place.reviews.map(review => review.rating); + const averageRating = reviewRatings.reduce((acc, curr) => acc + curr, 0) / reviewRatings.length; + res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); + } catch (error) { + console.error(error); + res.redirect('/'); + } }); -// // Add average rating functionality -// app.get('/places/:id', async (req, res) => { -// try { -// const place = await Place.findById(req.params.id).populate('reviews'); -// const reviewRatings = place.reviews.map(review => review.rating); -// const averageRating = reviewRatings.reduce((acc, curr) => acc + curr, 0) / reviewRatings.length; -// res.render('place_details', { place, averageRating }); -// } catch (error) { -// console.error(error); -// } -// }); - // // for modifying a place // app.post('/modify/:place_id', (req, res) => { // Place.findById(req.params.id) @@ -321,11 +315,7 @@ app.get('/places/:id', (req, res) => { /* ---------- [End] Place Routes ---------- */ -/* ---------- [Start] Ratings Routes ---------- */ - -/* ---------- [End] Ratings Routes ---------- */ - -/* ---------- [Start] Login/Register/Home Routes ---------- */ +/* ---------- [Start] Login/Register/Home/Forgot Password Routes ---------- */ // GET Route for Homes app.get('/', function (req, res) { @@ -511,4 +501,4 @@ app.listen(3000, function () { console.log("Server started at Port 3000!"); }); -/* ---------- [End] Login/Register/Home Routes ---------- */ \ No newline at end of file +/* ---------- [End] Login/Register/Home/Forgot Password Routes ---------- */ \ No newline at end of file diff --git a/views/all_places.ejs b/views/all_places.ejs index 95e004d68..8a51b22ce 100644 --- a/views/all_places.ejs +++ b/views/all_places.ejs @@ -11,11 +11,13 @@
  • <%= place.name %>

    <%= place.description %>

    +

    Average Rating: <%= place.avgRating %>

    +

    Number of Reviews: <%= place.numReviews %>

    Type: <%= place.placeType %>

    <% if (place.tags.length > 0) { %>

    Tags: <%= place.tags.join(', ') %>

    <% } %> -

    Location: <%= place.location.coordinates[1] %>, <%= place.location.coordinates[0] %>

    +

    Location: <%= place.name %> on Google Maps

    View

  • <% }); %> diff --git a/views/home.ejs b/views/home.ejs index 28ea819bd..76c43e110 100644 --- a/views/home.ejs +++ b/views/home.ejs @@ -9,6 +9,7 @@
    Register Login + Places diff --git a/views/place-details.ejs b/views/place-details.ejs index aee5d7eed..6f6b61eb5 100644 --- a/views/place-details.ejs +++ b/views/place-details.ejs @@ -2,8 +2,11 @@

    <%= place.description %>

    <%= place.placeType %>

    - +

    Average Rating:

    +

    <%= averageRating.toFixed(1) %>

    + +

    Number of Ratings:

    +

    <%= numRatings %>

    Location:

    <%= place.name %> on Google Maps

    @@ -13,7 +16,7 @@ <% place.reviews.forEach(function(review) { %>
  • <%= review.rating %> stars

    -

    <%= review.content %>

    +

    <%= review.text %>

  • <% }); %> -
+ \ No newline at end of file From e0fbb374c1a4503f02bf08d88d8f49d632cec1a2 Mon Sep 17 00:00:00 2001 From: Pramey Kabra Date: Fri, 24 Feb 2023 15:01:11 -0500 Subject: [PATCH 24/93] Major - Add functionality adding/removing/editing review + ratings Added dependency and new views Functioning - Add/Edit/Remove Reviews (on both indiv places and edit review page) --- app.js | 147 ++++++++++++++++++++++++++++++++++++++-- package-lock.json | 28 ++++++++ package.json | 1 + views/edit-review.ejs | 30 ++++++++ views/place-details.ejs | 55 +++++++++++---- views/reviews.ejs | 12 ++++ 6 files changed, 255 insertions(+), 18 deletions(-) create mode 100644 views/edit-review.ejs create mode 100644 views/reviews.ejs diff --git a/app.js b/app.js index 45e350684..46cd96b9d 100644 --- a/app.js +++ b/app.js @@ -11,6 +11,7 @@ const nodemailer = require('nodemailer'); const passport = require("passport"); const GoogleStrategy = require('passport-google-oauth20').Strategy; const findOrCreate = require('mongoose-findorcreate'); +const methodOverride = require('method-override'); const app = express(); @@ -37,6 +38,8 @@ const transporter = nodemailer.createTransport({ } }); +app.use(methodOverride('_method')); + app.use(express.static("public")); app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({ extended: true })); @@ -178,10 +181,6 @@ const reviewSchema = new Schema( ref: 'User', required: true, }, - // postLikeUsersList : [{ - // type: Schema.Types.ObjectId, - // ref: 'User', - // }] }, { timestamps: true } ); @@ -315,6 +314,145 @@ app.get('/places/:id', async (req, res) => { /* ---------- [End] Place Routes ---------- */ +/* ---------- [Start] Reviews Routes ---------- */ + +// Add a review +app.post('/places/:placeId/reviews', async (req, res) => { + const placeId = req.params.placeId; + const { rating, text } = req.body; + // const author = req.session.userId; // assuming user ID is stored in session + + try { + const place = await Place.findById(placeId); + + if (!place) { + return res.status(404).send('Place not found'); + } + + const review = new Review({ + rating, + text, + place: placeId, + author: mongoose.Types.ObjectId("63f7c45e51c4cfd2537c1b15"), + }); + + await review.save(); + + place.reviews.push(review); + await place.save(); + + res.redirect(`/places/${placeId}`); + + } catch (error) { + console.log(error); + res.status(500).send('Server error'); + } +}); + +// edit review +app.get('/places/:place_id/reviews/:id/edit', async (req, res) => { + const reviewId = req.params.id; + const placeId = req.params.place_id; + // const userId = req.session.userId; // assuming user ID is stored in session + + try { + const review = await Review.findById(reviewId); + + if (!review) { + return res.status(404).send('Review not found'); + } + + const place = await Place.findById(placeId); + + if (!place) { + return res.status(404).send('Place not found'); + } + + // if (review.author.toString() !== userId) { + // return res.status(403).send('Unauthorized'); + // } + + res.render('edit-review', { review, place }); + } catch (error) { + console.error(error); + res.status(500).send('Server error'); + } +}); + +app.put('/places/:place_id/reviews/:id', async (req, res) => { + const reviewId = req.params.id; + const placeId = req.params.place_id; + // const userId = req.session.userId; // assuming user ID is stored in session + const { rating, text } = req.body; + + try { + const review = await Review.findById(reviewId); + + if (!review) { + return res.status(404).send('Review not found'); + } + + const place = await Place.findById(placeId); + + if (!place) { + return res.status(404).send('Place not found'); + } + + // if (review.author.toString() !== userId) { + // return res.status(403).send('Unauthorized'); + // } + + review.rating = rating; + review.text = text; + await review.save(); + + res.redirect(`/places/${review.place}`); + } catch (error) { + console.log(error); + res.status(500).send('Server error'); + } +}); + +// delete review +app.delete('/places/:place_id/reviews/:id', async (req, res) => { + const reviewId = req.params.id; + // const userId = req.session.userId; // assuming user ID is stored in session + const placeId = req.params.place_id; + try { + const review = await Review.findById(reviewId); + + if (!review) { + return res.status(404).send('Review not found'); + } + + const place = await Place.findById(placeId); + + if (!place) { + return res.status(404).send('Place not found'); + } + + // if (review.author.toString() !== userId) { + // return res.status(403).send('Unauthorized'); + // } + + await Review.findByIdAndDelete(reviewId); + + await Place.findByIdAndUpdate( + placeId, + { $pull: { reviews: reviewId } }, + { new: true } + ); + + res.redirect(`/places/${placeId}`); + + } catch (error) { + console.log(error); + res.status(500).send('Server error'); + } +}); + +/* ---------- [End] Reviews Routes ---------- */ + /* ---------- [Start] Login/Register/Home/Forgot Password Routes ---------- */ // GET Route for Homes @@ -381,6 +519,7 @@ app.post('/login', function (req, res) { if (userExists) { if (userExists.password === userPass) { console.log("User Successfully Logged In!"); + // sessionStorage.setItem('userID', userExists._id); req.session.user = userExists; res.redirect("/landing"); } else { diff --git a/package-lock.json b/package-lock.json index 1c670d1a5..570d87416 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "express-session": "^1.17.3", "jsonwebtoken": "^9.0.0", "md5": "^2.3.0", + "method-override": "^3.0.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", "mongoose-findorcreate": "^3.0.0", @@ -2439,6 +2440,33 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, + "node_modules/method-override": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", + "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", + "dependencies": { + "debug": "3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/method-override/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/method-override/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", diff --git a/package.json b/package.json index 85e69b8a3..ebbb8c187 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "express-session": "^1.17.3", "jsonwebtoken": "^9.0.0", "md5": "^2.3.0", + "method-override": "^3.0.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", "mongoose-findorcreate": "^3.0.0", diff --git a/views/edit-review.ejs b/views/edit-review.ejs new file mode 100644 index 000000000..2fc5371bb --- /dev/null +++ b/views/edit-review.ejs @@ -0,0 +1,30 @@ + + + + + Edit Review + + +

Edit Review

+
+
+ + +
+
+ + +
+ +
+
+ +
+ + diff --git a/views/place-details.ejs b/views/place-details.ejs index 6f6b61eb5..9a6ec7d72 100644 --- a/views/place-details.ejs +++ b/views/place-details.ejs @@ -1,22 +1,49 @@

<%= place.name %>

-

<%= place.description %>

-

<%= place.placeType %>

-

Average Rating:

-

<%= averageRating.toFixed(1) %>

+
+

<%= place.description %>

+

<%= place.placeType %>

+

<%= place.tags.join(', ') %>

+

Average Rating: <%= averageRating %>

+

Number of Reviews: <%= numRatings %>

+
-

Number of Ratings:

-

<%= numRatings %>

- -

Location:

+

Location:

<%= place.name %> on Google Maps

-

Reviews

-
    +

    Reviews:

    + +<% if (place.reviews.length === 0) { %> +

    No reviews yet. Be the first to leave a review!

    +<% } else { %> <% place.reviews.forEach(function(review) { %> -
  • -

    <%= review.rating %> stars

    +
    +

    Rating: <%= review.rating %>

    <%= review.text %>

    -
  • +
    + +
    + Edit Review + <% }); %> -
\ No newline at end of file +<% } %> + +

Add a Review:

+ +
+
+ + +
+
+ + +
+ +
\ No newline at end of file diff --git a/views/reviews.ejs b/views/reviews.ejs new file mode 100644 index 000000000..43fd55639 --- /dev/null +++ b/views/reviews.ejs @@ -0,0 +1,12 @@ +

Reviews for <%= place.name %>:

+ +<% if (reviews.length === 0) { %> +

No reviews yet. Be the first to leave a review!

+<% } else { %> + <% reviews.forEach(function(review) { %> +
+

Rating: <%= review.rating %>

+

<%= review.text %>

+
+ <% }); %> +<% } %> From 7c3e7930ae6385494cad9892b8ff744e24d4f9e9 Mon Sep 17 00:00:00 2001 From: Pramey Kabra Date: Fri, 24 Feb 2023 15:38:55 -0500 Subject: [PATCH 25/93] Add helper function to round up/down ratings Status - working! --- app.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 46cd96b9d..35cc938ca 100644 --- a/app.js +++ b/app.js @@ -260,7 +260,7 @@ app.get('/places', async (req, res) => { const reviews = await Review.find({ place: place._id }); const totalRatings = reviews.reduce((acc, review) => acc + review.rating, 0); const numReviews = reviews.length > 0 ? reviews.length : 0; - const avgRating = reviews.length > 0 ? totalRatings / reviews.length : 0; + const avgRating = reviews.length > 0 ? roundToNearestHalf(totalRatings / reviews.length) : 0; return { ...place._doc, avgRating, numReviews }; })); res.render('all_places', { places: placesWithAvgRating }); @@ -277,7 +277,7 @@ app.get('/places/:id', async (req, res) => { const place = await Place.findById(req.params.id).populate('reviews'); // Add average rating functionality const reviewRatings = place.reviews.map(review => review.rating); - const averageRating = reviewRatings.reduce((acc, curr) => acc + curr, 0) / reviewRatings.length; + const averageRating = roundToNearestHalf(reviewRatings.reduce((acc, curr) => acc + curr, 0) / reviewRatings.length); res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); } catch (error) { console.error(error); @@ -640,4 +640,21 @@ app.listen(3000, function () { console.log("Server started at Port 3000!"); }); -/* ---------- [End] Login/Register/Home/Forgot Password Routes ---------- */ \ No newline at end of file +/* ---------- [End] Login/Register/Home/Forgot Password Routes ---------- */ + +/* ---------- [Start] Helper Functions ---------- */ + +function roundToNearestHalf(num) { + // Check if the number is within the desired range + if (num < 0 || num > 5) { + throw new Error('Number is not within the range of 0 and 5'); + } + + // Round to the nearest 0.5 + const roundedNum = Math.round(num * 2) / 2; + + // Ensure the rounded number is within the range of 0 and 5 + return Math.max(0, Math.min(5, roundedNum)); +} + +/* ---------- [End] Helper Functions ---------- */ \ No newline at end of file From 79307f354c285f217dc7de71752999588385d99a Mon Sep 17 00:00:00 2001 From: Antony Date: Sat, 25 Feb 2023 18:26:51 -0500 Subject: [PATCH 26/93] Adjusting for frontend integration --- app.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 35cc938ca..76aa99b9f 100644 --- a/app.js +++ b/app.js @@ -26,7 +26,13 @@ const corsOptions ={ app.use(cors(corsOptions)); mongoose.set('strictQuery', false); -mongoose.connect("mongodb://localhost:27017/allPurdueDB"); + +// for mac +// mongoose.connect("mongodb://localhost:27017/allPurdueDB"); + +// for windows +mongoose.connect("mongodb://127.0.0.1:27017/allPurdueDB"); + const transporter = nodemailer.createTransport({ service: 'gmail', host: 'smtp.gmail.com', @@ -263,7 +269,9 @@ app.get('/places', async (req, res) => { const avgRating = reviews.length > 0 ? roundToNearestHalf(totalRatings / reviews.length) : 0; return { ...place._doc, avgRating, numReviews }; })); - res.render('all_places', { places: placesWithAvgRating }); + // sending places as response + res.send(placesWithAvgRating) + // res.render('all_places', { places: placesWithAvgRating }); } catch (error) { console.error(error); res.status(500).send('Internal Server Error'); @@ -278,7 +286,9 @@ app.get('/places/:id', async (req, res) => { // Add average rating functionality const reviewRatings = place.reviews.map(review => review.rating); const averageRating = roundToNearestHalf(reviewRatings.reduce((acc, curr) => acc + curr, 0) / reviewRatings.length); - res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); + // sending place as response + res.send(place) + //res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); } catch (error) { console.error(error); res.redirect('/'); From b3c9cb452e08a366152c05fa593486891a08ad6e Mon Sep 17 00:00:00 2001 From: Antony Date: Sun, 26 Feb 2023 11:58:47 -0500 Subject: [PATCH 27/93] Login functionality changes (Google and normal) --- app.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 76aa99b9f..2d3e7ac4b 100644 --- a/app.js +++ b/app.js @@ -109,6 +109,8 @@ async function validateEmail(email) { const User = new mongoose.model("User", userSchema); +let currentUser = null; + // Place Schema const placeSchema = new Schema( @@ -211,12 +213,14 @@ passport.use(new GoogleStrategy({ clientID: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET, callbackURL: "http://localhost:3000/auth/google/allpurdue", + scope: ['profile', 'email'] }, function(accessToken, refreshToken, profile, cb) { User.findOrCreate({ googleId: profile.id, name: profile.displayName, email: profile.emails[0].value }, function (err, user) { if(err) { console.log(err); } + currentUser = user; return cb(err, user); }); } @@ -475,9 +479,11 @@ app.get("/auth/google", ); app.get("/auth/google/allpurdue", - passport.authenticate('google', { failureRedirect: "/login" }), + passport.authenticate('google', { failureRedirect: "http://localhost:3001/loginsignup" }), function(req, res, err) { - res.redirect("/landing"); + console.log("google login") + console.log(res.data) + res.redirect("http://localhost:3001/"); }); // GET Route for Register @@ -531,6 +537,7 @@ app.post('/login', function (req, res) { console.log("User Successfully Logged In!"); // sessionStorage.setItem('userID', userExists._id); req.session.user = userExists; + currentUser = userExists; res.redirect("/landing"); } else { console.log("Incorrect Password!"); @@ -545,6 +552,11 @@ app.post('/login', function (req, res) { ); }); +// GET Route for currentUser +app.get("/currentUser", function (req, res) { + res.send(currentUser); +}); + // GET Route for /forgotPassword app.get("/forgotPassword", function (req, res) { res.render("forgotPassword"); From e1a1493e540a4a6f22dead1c87d0175cd306e065 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 26 Feb 2023 15:59:48 -0500 Subject: [PATCH 28/93] Added users endpoint and updated add review endpoint --- app.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 2d3e7ac4b..e3b0558f7 100644 --- a/app.js +++ b/app.js @@ -228,6 +228,21 @@ function(accessToken, refreshToken, profile, cb) { /* ---------- [End] Google Auth ---------- */ +/* ---------- [Start] User Routes ---------- */ + +// GET route for retrieving all user data +app.get('/users', async (req, res) => { + try { + const users = await User.find(); + + res.json(users); + } catch (err) { + console.error(err); + res.status(500).send( 'Error retrieving user data' ); + } +}); + +/* ---------- [End] User Routes ---------- */ /* ---------- [Start] Place Routes ---------- */ @@ -333,8 +348,9 @@ app.get('/places/:id', async (req, res) => { // Add a review app.post('/places/:placeId/reviews', async (req, res) => { const placeId = req.params.placeId; - const { rating, text } = req.body; - // const author = req.session.userId; // assuming user ID is stored in session + const rating = req.body.rating; + const text = req.body.review; + const author = req.body.author; // assuming user ID is stored in session try { const place = await Place.findById(placeId); @@ -347,7 +363,7 @@ app.post('/places/:placeId/reviews', async (req, res) => { rating, text, place: placeId, - author: mongoose.Types.ObjectId("63f7c45e51c4cfd2537c1b15"), + author }); await review.save(); @@ -355,7 +371,7 @@ app.post('/places/:placeId/reviews', async (req, res) => { place.reviews.push(review); await place.save(); - res.redirect(`/places/${placeId}`); + res.status(201).json(review); } catch (error) { console.log(error); From d49f61e7f360ec9db4999c23bc59290fc9987f98 Mon Sep 17 00:00:00 2001 From: Antony Date: Mon, 27 Feb 2023 06:48:09 -0500 Subject: [PATCH 29/93] Change password endpoint --- app.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/app.js b/app.js index e3b0558f7..764ccee2e 100644 --- a/app.js +++ b/app.js @@ -656,6 +656,29 @@ app.post("/reset-password", function (req, res) { }) }); +// edit password from user dashboard page +app.post("/change-password", function (req, res) { + console.log(req.body.currentPassword) + User.findOne({ password: md5(req.body.currentPassword) }, function (err, user) { + if (err) { + console.log(err); + res.sendStatus(500); + } else if (!user) { + console.log("Current password does not match"); + res.status(400).send("Current password does not match"); + } else { + User.findOneAndUpdate({ _id: user._id }, { password: md5(req.body.newPassword) }, function (err) { + if (err) { + console.log(err); + res.sendStatus(500); + } else { + res.status(201).send("success") + } + }); + } + }); +}); + app.get("/logout", async function(req, res) { req.session.user = null; req.logout(function(err) { From 8117b0cd40b37676d13f57f3f1e3fd0bde7a9243 Mon Sep 17 00:00:00 2001 From: Antony Date: Mon, 27 Feb 2023 06:52:55 -0500 Subject: [PATCH 30/93] Sending error to frontend if unsuccessful login --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 764ccee2e..1136b53e9 100644 --- a/app.js +++ b/app.js @@ -557,7 +557,7 @@ app.post('/login', function (req, res) { res.redirect("/landing"); } else { console.log("Incorrect Password!"); - res.redirect("/login"); + res.status(500).send("Incorrect Password!") } } else { console.log("User not found!"); From 7f86f8633c97b904fd07ff4264dd778b713ae1ee Mon Sep 17 00:00:00 2001 From: Antony Date: Mon, 27 Feb 2023 07:19:38 -0500 Subject: [PATCH 31/93] Endpoint for request submission from Contact page --- app.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 1136b53e9..d9af13303 100644 --- a/app.js +++ b/app.js @@ -658,7 +658,6 @@ app.post("/reset-password", function (req, res) { // edit password from user dashboard page app.post("/change-password", function (req, res) { - console.log(req.body.currentPassword) User.findOne({ password: md5(req.body.currentPassword) }, function (err, user) { if (err) { console.log(err); @@ -718,4 +717,24 @@ function roundToNearestHalf(num) { return Math.max(0, Math.min(5, roundedNum)); } -/* ---------- [End] Helper Functions ---------- */ \ No newline at end of file +/* ---------- [End] Helper Functions ---------- */ + +// contact page submission +app.post("/submit-request", function (req, res) { + console.log("getting here") + const msg = { + from: '"Team AllPurdue" allpurdue2023@gmail.com', + to: '"Team AllPurdue" allpurdue2023@gmail.com', + subject: req.body.requestType + ' request from ' + req.body.email, + text: req.body.requestType === 'Add Place' ? req.body.name + '\n' + req.body.message : 'Report Issue' + '\n' + req.body.message + } + transporter.sendMail(msg, function(err){ + if (err) { + console.log(err); + res.status(500).send("error submitting request") + } else { + console.log("successful request submission"); + res.status(200).send("success") + } + }); +}); \ No newline at end of file From 6f5484ad3412d7e6120d96a347728bb943ec2147 Mon Sep 17 00:00:00 2001 From: Antony Date: Mon, 27 Feb 2023 10:52:28 -0500 Subject: [PATCH 32/93] Adding error and success messages for login/signup --- app.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index d9af13303..62f996c16 100644 --- a/app.js +++ b/app.js @@ -521,7 +521,7 @@ app.post('/register', function (req, res) { console.log(req.body); if(req.body.password.length < 6) { console.log("Password length is less than 6!"); - return res.redirect('/register'); + res.status(500).send('Password length is less than 6!'); } const newUser = new User({ name: req.body.name, @@ -531,7 +531,7 @@ app.post('/register', function (req, res) { newUser.save(function (err) { if (err) { console.log(err); - res.sendStatus(500); + res.status(500).send('Unsuccessful registration'); } else { console.log("User Successfully Registered!"); res.render("login"); @@ -547,6 +547,7 @@ app.post('/login', function (req, res) { User.findOne({ email: username }, function (err, userExists) { if (err) { console.log(err); + res.status(500).send('User not found') } else { if (userExists) { if (userExists.password === userPass) { @@ -557,11 +558,11 @@ app.post('/login', function (req, res) { res.redirect("/landing"); } else { console.log("Incorrect Password!"); - res.status(500).send("Incorrect Password!") + res.status(500).send("Incorrect Password") } } else { console.log("User not found!"); - res.redirect("/login"); + res.status(500).send('Email does not exist') } } } From c7c587e30e911e32e4303a1c2b837bdddaf7c5e2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Feb 2023 11:43:16 -0500 Subject: [PATCH 33/93] Endpoint to like and unlike a review --- app.js | 131 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 44 deletions(-) diff --git a/app.js b/app.js index d9af13303..f22ca0c0c 100644 --- a/app.js +++ b/app.js @@ -89,7 +89,11 @@ const userSchema = new Schema( }], googleId: { type: String - } + }, + likedReviews: [{ + type: Schema.Types.ObjectId, + ref: 'Review', + }] }, { timestamps: true } ); @@ -169,29 +173,37 @@ const Place = new mongoose.model("Place", placeSchema); // Reviews Schema const reviewSchema = new Schema( - { - rating: { - type: Number, - minimum: [1, "Minimum rating of 1 is required"], - maximum: [5, "Maximum rating of 5 is required"], - required: true, - }, - text: { - type: String, - }, - place: { - type: Schema.Types.ObjectId, - ref: 'Place', - required: true, - }, - author: { - type: Schema.Types.ObjectId, - ref: 'User', - required: true, - }, + { + rating: { + type: Number, + minimum: [1, "Minimum rating of 1 is required"], + maximum: [5, "Maximum rating of 5 is required"], + required: true, }, - { timestamps: true } - ); + text: { + type: String, + }, + place: { + type: Schema.Types.ObjectId, + ref: 'Place', + required: true, + }, + author: { + type: Schema.Types.ObjectId, + ref: 'User', + required: true, + }, + likes: { + type: Number, + default: 0, + }, + likes_by: [{ + type: Schema.Types.ObjectId, + ref: 'User', + }], + }, + { timestamps: true } +); const Review = new mongoose.model("Review", reviewSchema); @@ -242,6 +254,16 @@ app.get('/users', async (req, res) => { } }); +// GET route for getting specific user +app.get('/users/:id', async (req, res) => { + try { + const user = await User.findById(req.params.id); + res.send(user) + } catch (error) { + console.error(error); + } +}); + /* ---------- [End] User Routes ---------- */ /* ---------- [Start] Place Routes ---------- */ @@ -481,6 +503,46 @@ app.delete('/places/:place_id/reviews/:id', async (req, res) => { } }); +// Like a review +app.post('/reviews/:reviewId/like/:userId', async (req, res) => { + const reviewId = req.params.reviewId; + console.log(req.params.userId) + const user = await User.findById(req.params.userId); + console.log(user) + + try { + const review = await Review.findById(reviewId); + + if (!review) { + return res.status(404).send('Review not found'); + } + + const hasLiked = review.likes_by.includes(user._id); + console.log(hasLiked) + + if (hasLiked) { + review.likes = review.likes - 1; + review.likes_by.pop(user._id); + user.likedReviews.pop(review._id); + } else { + review.likes = review.likes + 1; + review.likes_by.push(user._id); + console.log(user.likedReviews); + user.likedReviews.push(review._id); + console.log(user.likedReviews); + } + + // Save the changes to the review and user documents + await review.save(); + // await user.save(); + + return res.json({ review }); + } catch (error) { + console.log(error); + res.status(500).send('Server error'); + } +}); + /* ---------- [End] Reviews Routes ---------- */ /* ---------- [Start] Login/Register/Home/Forgot Password Routes ---------- */ @@ -658,6 +720,7 @@ app.post("/reset-password", function (req, res) { // edit password from user dashboard page app.post("/change-password", function (req, res) { + console.log(req.body.currentPassword) User.findOne({ password: md5(req.body.currentPassword) }, function (err, user) { if (err) { console.log(err); @@ -717,24 +780,4 @@ function roundToNearestHalf(num) { return Math.max(0, Math.min(5, roundedNum)); } -/* ---------- [End] Helper Functions ---------- */ - -// contact page submission -app.post("/submit-request", function (req, res) { - console.log("getting here") - const msg = { - from: '"Team AllPurdue" allpurdue2023@gmail.com', - to: '"Team AllPurdue" allpurdue2023@gmail.com', - subject: req.body.requestType + ' request from ' + req.body.email, - text: req.body.requestType === 'Add Place' ? req.body.name + '\n' + req.body.message : 'Report Issue' + '\n' + req.body.message - } - transporter.sendMail(msg, function(err){ - if (err) { - console.log(err); - res.status(500).send("error submitting request") - } else { - console.log("successful request submission"); - res.status(200).send("success") - } - }); -}); \ No newline at end of file +/* ---------- [End] Helper Functions ---------- */ \ No newline at end of file From b9f3fbe4e69bd407bdddf1c075c5532de03c4193 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Feb 2023 11:44:43 -0500 Subject: [PATCH 34/93] Endpoint to like and unlike a review --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index f22ca0c0c..614755478 100644 --- a/app.js +++ b/app.js @@ -503,7 +503,7 @@ app.delete('/places/:place_id/reviews/:id', async (req, res) => { } }); -// Like a review +// Like and unlike a review app.post('/reviews/:reviewId/like/:userId', async (req, res) => { const reviewId = req.params.reviewId; console.log(req.params.userId) From 73d9b205be44f85f1c6e81b22348fc3f2ecf7488 Mon Sep 17 00:00:00 2001 From: Antony Date: Mon, 27 Feb 2023 17:56:52 -0500 Subject: [PATCH 35/93] Suggested places of a place --- app.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 62f996c16..1b838f8fb 100644 --- a/app.js +++ b/app.js @@ -305,12 +305,24 @@ app.get('/places/:id', async (req, res) => { // Add average rating functionality const reviewRatings = place.reviews.map(review => review.rating); const averageRating = roundToNearestHalf(reviewRatings.reduce((acc, curr) => acc + curr, 0) / reviewRatings.length); - // sending place as response - res.send(place) + + // suggestions + const tags = place.tags; + const suggestedPlaces = await Place.find({tags:{$in:tags}, _id:{$ne: place._id}}).limit(5); + // if there aren't 5 places with matching tags then we check for matching placeType + if (suggestedPlaces.length < 5) { + const matchingPlaceTypes = await Place.find({placeType: place.placeType, _id:{$ne: place._id}}).limit(5 - suggestedPlaces.length); + suggestedPlaces.push(...matchingPlaceTypes); + } + + // sending everything as response + const data = { place, reviewRatings, averageRating, suggestedPlaces }; + res.send(data) //res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); } catch (error) { console.error(error); - res.redirect('/'); + // res.redirect('/'); + res.status(400).send("Error retrieving place data") } }); From b0ec2e930e5ebd889d7f0b199ffc5e9d433b9ba3 Mon Sep 17 00:00:00 2001 From: Antony Date: Tue, 28 Feb 2023 08:47:03 -0500 Subject: [PATCH 36/93] Set current user to null when user logs out --- app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app.js b/app.js index 1b838f8fb..6bd612a2f 100644 --- a/app.js +++ b/app.js @@ -693,6 +693,7 @@ app.post("/change-password", function (req, res) { app.get("/logout", async function(req, res) { req.session.user = null; + currentUser = null; req.logout(function(err) { if (err) { return next(err); } res.redirect('/'); From 8231208812b5eafec575dc50dafe850923e1df74 Mon Sep 17 00:00:00 2001 From: Antony Date: Tue, 28 Feb 2023 09:44:14 -0500 Subject: [PATCH 37/93] Recent reviews endpoint --- app.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app.js b/app.js index 6bd612a2f..49f307627 100644 --- a/app.js +++ b/app.js @@ -357,6 +357,22 @@ app.get('/places/:id', async (req, res) => { /* ---------- [Start] Reviews Routes ---------- */ +// getting recent reviews +app.get('/recent-reviews', async (req, res) => { + try { + const recentReviews = await Review.find({}) + .populate('place', 'name tags placeType') + .sort({ updatedAt: -1 }) + .exec() + + // sending recentReviews as response + res.send(recentReviews) + } catch (error) { + console.error(error); + res.status(500).send('Internal Server Error'); + } +}) + // Add a review app.post('/places/:placeId/reviews', async (req, res) => { const placeId = req.params.placeId; From 421f2d0e3b8c0ec6574d1c126173769c09d06b24 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Feb 2023 10:32:21 -0500 Subject: [PATCH 38/93] Adding missing endpoints back --- app.js | 114 +++++++++++++++++++++++++++------------------------------ 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/app.js b/app.js index b5edf3ddf..2f20edad2 100644 --- a/app.js +++ b/app.js @@ -89,11 +89,7 @@ const userSchema = new Schema( }], googleId: { type: String - }, - likedReviews: [{ - type: Schema.Types.ObjectId, - ref: 'Review', - }] + } }, { timestamps: true } ); @@ -173,37 +169,37 @@ const Place = new mongoose.model("Place", placeSchema); // Reviews Schema const reviewSchema = new Schema( - { - rating: { - type: Number, - minimum: [1, "Minimum rating of 1 is required"], - maximum: [5, "Maximum rating of 5 is required"], - required: true, - }, - text: { - type: String, - }, - place: { - type: Schema.Types.ObjectId, - ref: 'Place', - required: true, - }, - author: { - type: Schema.Types.ObjectId, - ref: 'User', - required: true, - }, - likes: { - type: Number, - default: 0, + { + rating: { + type: Number, + minimum: [1, "Minimum rating of 1 is required"], + maximum: [5, "Maximum rating of 5 is required"], + required: true, + }, + text: { + type: String, + }, + place: { + type: Schema.Types.ObjectId, + ref: 'Place', + required: true, + }, + author: { + type: Schema.Types.ObjectId, + ref: 'User', + required: true, + }, + likes: { + type: Number, + default: 0, + }, + likes_by: [{ + type: Schema.Types.ObjectId, + ref: 'User', + }] }, - likes_by: [{ - type: Schema.Types.ObjectId, - ref: 'User', - }], - }, - { timestamps: true } -); + { timestamps: true } + ); const Review = new mongoose.model("Review", reviewSchema); @@ -254,16 +250,6 @@ app.get('/users', async (req, res) => { } }); -// GET route for getting specific user -app.get('/users/:id', async (req, res) => { - try { - const user = await User.findById(req.params.id); - res.send(user) - } catch (error) { - console.error(error); - } -}); - /* ---------- [End] User Routes ---------- */ /* ---------- [Start] Place Routes ---------- */ @@ -480,7 +466,6 @@ app.put('/places/:place_id/reviews/:id', async (req, res) => { // delete review app.delete('/places/:place_id/reviews/:id', async (req, res) => { const reviewId = req.params.id; - // const userId = req.session.userId; // assuming user ID is stored in session const placeId = req.params.place_id; try { const review = await Review.findById(reviewId); @@ -494,10 +479,6 @@ app.delete('/places/:place_id/reviews/:id', async (req, res) => { if (!place) { return res.status(404).send('Place not found'); } - - // if (review.author.toString() !== userId) { - // return res.status(403).send('Unauthorized'); - // } await Review.findByIdAndDelete(reviewId); @@ -518,9 +499,7 @@ app.delete('/places/:place_id/reviews/:id', async (req, res) => { // Like and unlike a review app.post('/reviews/:reviewId/like/:userId', async (req, res) => { const reviewId = req.params.reviewId; - console.log(req.params.userId) const user = await User.findById(req.params.userId); - console.log(user) try { const review = await Review.findById(reviewId); @@ -530,18 +509,15 @@ app.post('/reviews/:reviewId/like/:userId', async (req, res) => { } const hasLiked = review.likes_by.includes(user._id); - console.log(hasLiked) if (hasLiked) { review.likes = review.likes - 1; review.likes_by.pop(user._id); - user.likedReviews.pop(review._id); + // user.likedReviews.pop(review._id); } else { review.likes = review.likes + 1; review.likes_by.push(user._id); - console.log(user.likedReviews); - user.likedReviews.push(review._id); - console.log(user.likedReviews); + // user.likedReviews.push(review._id); } // Save the changes to the review and user documents @@ -733,7 +709,6 @@ app.post("/reset-password", function (req, res) { // edit password from user dashboard page app.post("/change-password", function (req, res) { - console.log(req.body.currentPassword) User.findOne({ password: md5(req.body.currentPassword) }, function (err, user) { if (err) { console.log(err); @@ -756,7 +731,6 @@ app.post("/change-password", function (req, res) { app.get("/logout", async function(req, res) { req.session.user = null; - currentUser = null; req.logout(function(err) { if (err) { return next(err); } res.redirect('/'); @@ -794,4 +768,24 @@ function roundToNearestHalf(num) { return Math.max(0, Math.min(5, roundedNum)); } -/* ---------- [End] Helper Functions ---------- */ \ No newline at end of file +/* ---------- [End] Helper Functions ---------- */ + +// contact page submission +app.post("/submit-request", function (req, res) { + console.log("getting here") + const msg = { + from: '"Team AllPurdue" allpurdue2023@gmail.com', + to: '"Team AllPurdue" allpurdue2023@gmail.com', + subject: req.body.requestType + ' request from ' + req.body.email, + text: req.body.requestType === 'Add Place' ? req.body.name + '\n' + req.body.message : 'Report Issue' + '\n' + req.body.message + } + transporter.sendMail(msg, function(err){ + if (err) { + console.log(err); + res.status(500).send("error submitting request") + } else { + console.log("successful request submission"); + res.status(200).send("success") + } + }); +}); \ No newline at end of file From b757344cafdc64748993db2b327b171269e3cf69 Mon Sep 17 00:00:00 2001 From: raseshr Date: Tue, 28 Feb 2023 16:32:36 -0500 Subject: [PATCH 39/93] Added search routes and queries --- app.js | 43 +++++++++++++++++++++++++++++++++ views/search.ejs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 views/search.ejs diff --git a/app.js b/app.js index 2f20edad2..050b40e2e 100644 --- a/app.js +++ b/app.js @@ -363,6 +363,49 @@ app.get('/places/:id', async (req, res) => { /* ---------- [End] Place Routes ---------- */ +/* ---------- [Start] Search Routes ---------- */ + +// Set up the search endpoint route to handle GET requests +app.get('/search', async (req, res) => { + try { + //const query = req.query.q || ''; + const results = []; // No results to show yet + //res.render('search', { results }); + res.render('search', { results, query: null }); + } catch (err) { + console.error(err); + res.render('error', { message: 'An error has occurred' }); + } +}); + +// Set up the search endpoint to handle POST requests +app.post('/search' , async (req, res) => { + const query = req.body.query; + const regexQuery = new RegExp(query, 'i'); + // console.log(regexQuery); + try { + const results = await Place.find({ + $or: [ + { name: regexQuery }, + { placeType: regexQuery }, + { tags: regexQuery }, + ] + }).select('name placeType tags').limit(3); + console.log(results); + res.send(results) + // if (req.xhr) { + // res.json({results }); // Return JSON containing the autocomplete suggestions + // } else { + // res.render('search', { results }); + // } + } catch (err) { + console.error(err); + // res.render('error', { message: 'An error has occurred' }); + } +}); + +/* ---------- [End] search Routes ---------- */ + /* ---------- [Start] Reviews Routes ---------- */ // Add a review diff --git a/views/search.ejs b/views/search.ejs new file mode 100644 index 000000000..f4a4ebfa9 --- /dev/null +++ b/views/search.ejs @@ -0,0 +1,63 @@ + + + + + Search + + + + + +
+

All Purdue

+ +
+
+

Search

+
+ + + + +
+
+
+ + + \ No newline at end of file From 70ce25c8026e733e21c26a3b09fe8b6738599f20 Mon Sep 17 00:00:00 2001 From: raseshr Date: Tue, 28 Feb 2023 16:35:26 -0500 Subject: [PATCH 40/93] Added images field --- app.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 050b40e2e..2663d93f5 100644 --- a/app.js +++ b/app.js @@ -147,7 +147,12 @@ const placeSchema = new Schema( reviews: [{ type: Schema.Types.ObjectId, ref: 'Review', - }] + }], + images: [ + { + type: String, + }, + ], }, { timestamps: true } ); From 5f84b12a84b8a85973d353e6c23ca6ec9743f1e6 Mon Sep 17 00:00:00 2001 From: raseshr Date: Tue, 28 Feb 2023 16:36:18 -0500 Subject: [PATCH 41/93] Added images field --- app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 2663d93f5..05b796375 100644 --- a/app.js +++ b/app.js @@ -151,8 +151,8 @@ const placeSchema = new Schema( images: [ { type: String, - }, - ], + }, + ] }, { timestamps: true } ); From 450f9fc094d52f23259c4916ef6880dbbd4d6a26 Mon Sep 17 00:00:00 2001 From: raseshr Date: Tue, 28 Feb 2023 19:34:39 -0500 Subject: [PATCH 42/93] Added new fields for places --- addPlaces.sql | 490 ++++++++++++++++++++++++++++++++++++++++++++++++++ app.js | 14 +- 2 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 addPlaces.sql diff --git a/addPlaces.sql b/addPlaces.sql new file mode 100644 index 000000000..36d3c217b --- /dev/null +++ b/addPlaces.sql @@ -0,0 +1,490 @@ +db.places.insert( + +) + + +db.places.insertMany([ + { + name: 'Hala''s Grill', + description: 'Modest counter-serve for Middle Eastern bowls with protein options, plus sides.', + placeType: 'Food', + tags: [ 'Middle Eastern', 'Healthy', 'Local', 'Home-Made', 'Chauncey', 'Bowl', 'Fries' ], + location: { type: 'Point', coordinates: [40.423304605885455, -86.907737172374] }, + reviews: [ ], + images: ['https://tinyurl.com/halaslogo', 'https://tinyurl.com/halabowl', 'https://tinyurl.com/halasfries'], + address: '135 S Chauncey Ave #2G, West Lafayette, IN 47906', + googleMap: 'https://www.google.com/maps/place/Hala''s+Grill/@40.4229005,-86.9078096,17z/data=!3m1!4b1!4m6!3m5!1s0x8812e373c4bc8363:0x1df2c0530eee7a7a!8m2!3d40.4229005!4d-86.9078096!16s%2Fg%2F11hkfkjj_g', + website: 'https://www.halasgrill.com/' + }, + { + name: 'Five Guys', + description: 'Fast-food chain with made-to-order burgers, fries & hot dogs, milkshakes, and free peanuts while you wait.', + placeType: 'Food', + tags: [ 'Fast Food', 'American', 'Burgers', 'Fries', 'Milkshakes', 'Chain', 'Chauncey' ], + location: { type: 'Point', coordinates: [40.42343994609269, -86.90795109977412] }, + reviews: [ ], + images: ['https://tinyurl.com/fiveguysfood', 'https://tinyurl.com/5guysinsidewl'], + address: '135 S Chauncey Ave Suite 1-K, West Lafayette, IN 47906', + googleMap: 'https://www.google.com/maps/place/Five+Guys/@40.4233731,-86.9122599,17.05z/data=!4m6!3m5!1s0x8812e2aed99721e9:0x2a65fca44b4f0116!8m2!3d40.4233321!4d-86.9080151!16s%2Fg%2F1tvq4qs0', + website: 'https://restaurants.fiveguys.com/135-s-chauncey-avenue' + }, + { + name: 'Insomnia Cookies', + description: 'Bakery chain known for warm & fresh cookies, open late-night, and also selling ice cream.', + placeType: 'Food', + tags: ['Desserts', 'Cookies', 'Ice Cream', 'Open Late', 'Chain', 'On Campus'], + location: { type: 'Point', coordinates: [40.431694360504636, -86.91303583596788] }, + reviews: [ ], + images: ['https://tinyurl.com/insomniacookieslogo', 'https://tinyurl.com/insomniacookiespurdue'], + address: '602 W Stadium Ave, West Lafayette, IN 47906', + googleMap: 'https://www.google.com/maps/place/Insomnia+Cookies/@40.4315727,-86.9151089,17z/data=!4m15!1m8!3m7!1s0x8812fd4d4fe0373f:0x6ba1b40af4af0021!2sInsomnia+Cookies!8m2!3d40.4315727!4d-86.9130013!10e1!16s%2Fg%2F1vxw8wg_!3m5!1s0x8812fd4d4fe0373f:0x6ba1b40af4af0021!8m2!3d40.4315727!4d-86.9130013!16s%2Fg%2F1vxw8wg_', + website: 'https://insomniacookies.com/menu/17' + }, + { + name: 'Mad Mushroom', + description: 'Local pizza chain dishing up a wide variety of pies, grinders, pasta & salads. Most known for its Cheesestix.', + placeType: 'Food', + tags: [ 'Pizza', 'American', 'Italian', 'Local', 'Chain', 'Chauncey', 'On Campus', 'Open Late', 'Alcohol' ], + location: { type: 'Point', coordinates: [40.42426763341673, -86.90904218988186] }, + reviews: [ ], + images: ['https://tinyurl.com/madmushroomlogo', 'https://tinyurl.com/madmushpies'], + address: '320 W State St, West Lafayette, IN 47906', + googleMap: 'https://www.google.com/maps/place/Mad+Mushroom/@40.4241043,-86.9111746,17z/data=!3m1!4b1!4m6!3m5!1s0x8812fd4d1c8bf8cb:0xf26797ec22ddf82c!8m2!3d40.4241002!4d-86.9089859!16s%2Fg%2F12cpby27w', + website: 'https://www.madmushroom.com/west-lafayette' + }, + { + name: 'Maru Sushi', + description: 'Happening eatery serving up sushi & other traditional Japanese staples in a minuscule space.', + placeType: 'Food', + tags: [ 'Asian', 'Japanese', 'Sushi', 'Chauncey', 'Local' ], + location: { type: 'Point', coordinates: [40.42470168147317, -86.90665652715337] }, + reviews: [ ], + images: ['https://tinyurl.com/marusushilogopurdue', 'https://tinyurl.com/marusushipurduesushiplate'], + address: '102 N Chauncey Ave D, West Lafayette, IN 47906', + googleMap: 'https://www.google.com/maps/place/Maru+Sushi/@40.4245016,-86.9089847,17z/data=!3m1!4b1!4m6!3m5!1s0x8812e2a936645567:0xde255f15b5d68628!8m2!3d40.4245016!4d-86.906796!16s%2Fg%2F1vzg2vgk', + website: 'https://maru-sushi.us/' + }, + { + name: 'Bruno''s Pizza and Big O''s Sports Room', + description: 'American, Italian & some German dishes, plus a full bar, in a Swiss chalet-type setting.', + placeType: 'Food', + tags: [ 'Pizza', 'American', 'German', 'Italian', 'Alcohol', 'Local', 'Wabash Landing' ], + location: { type: 'Point', coordinates: [40.42252768794087, -86.90299580387695] }, + reviews: [ ], + images: ['https://tinyurl.com/brunoslogowl', 'https://tinyurl.com/brunospizzawlpizza', 'https://tinyurl.com/brunosdoughsplwl'], + address: '212 Brown St, West Lafayette, IN 47906', + googleMap: 'https://www.google.com/maps/place/Bruno''s+Pizza+and+Big+O''s+Sports+Room/@40.4223276,-86.9051094,17z/data=!4m15!1m8!3m7!1s0x8812e2a82517cf6d:0x81d1a879bb1aecda!2sBruno''s+Pizza+and+Big+O''s+Sports+Room!8m2!3d40.4223276!4d-86.9029207!10e1!16s%2Fg%2F1tgyx9kh!3m5!1s0x8812e2a82517cf6d:0x81d1a879bb1aecda!8m2!3d40.4223276!4d-86.9029207!16s%2Fg%2F1tgyx9kh', + website: 'http://brunodough.com/' + }, + { + name: 'Strings Ramen', + description: 'Restaurant with great ambiance offering Ramen as well as other Japanese side dishes.', + placeType: 'Food', + tags: [ 'Asian', 'Japanese', 'Ramen', 'Chauncey', 'Chain', 'Local' ], + location: { type: 'Point', coordinates: [40.42417961049075, -86.90706417318749] }, + reviews: [ ], + images: ['https://tinyurl.com/stringsramenlogo', 'https://tinyurl.com/stringsramenfood'], + address: '103 N Chauncey Ave, West Lafayette, IN 47906', + googleMap: 'https://www.google.com/maps/place/Strings+Ramen+Purdue/@40.4240367,-86.9092636,17z/data=!4m6!3m5!1s0x8812e3e71476fe81:0x489bc752b37b9cad!8m2!3d40.4240367!4d-86.9070749!16s%2Fg%2F11rwrz6c32', + website: 'https://www.stringsramen.com/' + }, + { + name: '', + description: '', + placeType: 'Food', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Food', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Food', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: 'Red Wok', + description: 'Chinese Food Place', + placeType: 'Food', + tags: [ 'Chinese', 'Asian', 'Open Late', 'Local', 'Chauncey' ], + location: { type: 'Point', coordinates: [ 40.42313730000001, -86.9087126 ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: 'Chipotle', + description: 'Mexican Food Place', + placeType: 'Food', + tags: [ 'Mexican', 'Healthy', 'Chain' ], + location: { type: 'Point', coordinates: [ 40.4236301, -86.9101227 ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: 'Silver Dipper', + description: 'Ice Cream Place', + placeType: 'Food', + tags: [ 'Ice Cream', 'Desserts', 'Local', 'Wabash Landing' ], + location: { type: 'Point', coordinates: [ 40.4197746, -86.91205520000001 ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Cafe', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Cafe', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Cafe', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Cafe', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Cafe', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Cafe', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Cafe', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Study', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: 'WALC', + description: 'Library', + placeType: 'Study', + tags: [ 'Library', 'Printers' ], + location: { type: 'Point', coordinates: [ 40.4276319, -86.91326409999999 ] }, + reviews: [], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: '', + description: '', + placeType: 'Living', + tags: [ '' ], + location: { type: 'Point', coordinates: [ , ] }, + reviews: [ ], + images: [ ], + address: '', + googleMap: '', + website: '' + }, + { + name: 'Hillenbrand Hall', + description: 'Residence Hall', + placeType: 'Living', + tags: [ 'Learning Community', 'Dining Court' ], + location: { + type: 'Point', + coordinates: [ 40.42669962268096, -86.92667082832517 ] + }, + reviews: [], + images: [ ], + address: '', + googleMap: '', + website: '' + }, +]) \ No newline at end of file diff --git a/app.js b/app.js index 05b796375..d06bd9e2d 100644 --- a/app.js +++ b/app.js @@ -152,7 +152,19 @@ const placeSchema = new Schema( { type: String, }, - ] + ], + address: { + type: String, + required: true, + }, + googleMap: { + type: String, + required: true, + }, + website: { + type: String, + required: true, + } }, { timestamps: true } ); From cf2bb61324ef17030e92e7f651c625f4811099a7 Mon Sep 17 00:00:00 2001 From: Antony Date: Wed, 1 Mar 2023 08:33:45 -0500 Subject: [PATCH 43/93] currentUser null --- app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 8a25d069b..09e32f6d7 100644 --- a/app.js +++ b/app.js @@ -793,7 +793,7 @@ app.post("/change-password", function (req, res) { console.log("Current password does not match"); res.status(400).send("Current password does not match"); } else { - User.findOneAndUpdate({ _id: user._id }, { password: md5(req.body.newPassword) }, function (err) { + User.findOneAndUpdate({ _id: req.body.userId }, { password: md5(req.body.newPassword) }, function (err) { if (err) { console.log(err); res.sendStatus(500); @@ -807,6 +807,7 @@ app.post("/change-password", function (req, res) { app.get("/logout", async function(req, res) { req.session.user = null; + currentUser = null req.logout(function(err) { if (err) { return next(err); } res.redirect('/'); From 52305a5edda19c5b7471156988ffc7a6748c7dec Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Mar 2023 09:51:32 -0500 Subject: [PATCH 44/93] Updated places endpoints to retrieve new placeSchema data --- app.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 09e32f6d7..c411fb698 100644 --- a/app.js +++ b/app.js @@ -340,8 +340,12 @@ app.get('/places/:id', async (req, res) => { suggestedPlaces.push(...matchingPlaceTypes); } + const website = place.website; + const address = place.address; + const googleMap = place.googleMap; + // sending everything as response - const data = { place, reviewRatings, averageRating, suggestedPlaces }; + const data = { place, reviewRatings, averageRating, suggestedPlaces, website, address, googleMap }; res.send(data) //res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); } catch (error) { From fd3a6a7005ea7d81409055459d99c00f53d4a410 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Mar 2023 10:30:17 -0500 Subject: [PATCH 45/93] Specific user retrieval endpoint --- app.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app.js b/app.js index c411fb698..a4b8661c5 100644 --- a/app.js +++ b/app.js @@ -267,6 +267,16 @@ app.get('/users', async (req, res) => { } }); +// GET route for getting specific user +app.get('/users/:id', async (req, res) => { + try { + const user = await User.findById(req.params.id); + res.send(user) + } catch (error) { + console.error(error); + } +}); + /* ---------- [End] User Routes ---------- */ /* ---------- [Start] Place Routes ---------- */ From 0a793b491fda6ec23f9a1c746b8d49c9a9ffce88 Mon Sep 17 00:00:00 2001 From: Antony Date: Wed, 1 Mar 2023 18:24:44 -0500 Subject: [PATCH 46/93] sending images for search query --- app.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index a4b8661c5..a56269b95 100644 --- a/app.js +++ b/app.js @@ -421,7 +421,7 @@ app.post('/search' , async (req, res) => { { placeType: regexQuery }, { tags: regexQuery }, ] - }).select('name placeType tags').limit(3); + }).select('name placeType tags images').limit(3); console.log(results); res.send(results) // if (req.xhr) { @@ -443,7 +443,7 @@ app.post('/search' , async (req, res) => { app.get('/recent-reviews', async (req, res) => { try { const recentReviews = await Review.find({}) - .populate('place', 'name tags placeType') + .populate('place', 'name tags placeType images') .sort({ updatedAt: -1 }) .exec() @@ -469,6 +469,10 @@ app.post('/places/:placeId/reviews', async (req, res) => { return res.status(404).send('Place not found'); } + if (rating === null || rating < 1) { + return res.status(400).send('Please select rating of at least 1') + } + const review = new Review({ rating, text, From f6d591258bd2e3d65be4c538930a571cde23bfd0 Mon Sep 17 00:00:00 2001 From: raseshr Date: Wed, 1 Mar 2023 19:04:30 -0500 Subject: [PATCH 47/93] added hours and phone fields to place schema --- addPlaces.sql | 490 -------------------------------------------------- app.js | 8 + 2 files changed, 8 insertions(+), 490 deletions(-) delete mode 100644 addPlaces.sql diff --git a/addPlaces.sql b/addPlaces.sql deleted file mode 100644 index 36d3c217b..000000000 --- a/addPlaces.sql +++ /dev/null @@ -1,490 +0,0 @@ -db.places.insert( - -) - - -db.places.insertMany([ - { - name: 'Hala''s Grill', - description: 'Modest counter-serve for Middle Eastern bowls with protein options, plus sides.', - placeType: 'Food', - tags: [ 'Middle Eastern', 'Healthy', 'Local', 'Home-Made', 'Chauncey', 'Bowl', 'Fries' ], - location: { type: 'Point', coordinates: [40.423304605885455, -86.907737172374] }, - reviews: [ ], - images: ['https://tinyurl.com/halaslogo', 'https://tinyurl.com/halabowl', 'https://tinyurl.com/halasfries'], - address: '135 S Chauncey Ave #2G, West Lafayette, IN 47906', - googleMap: 'https://www.google.com/maps/place/Hala''s+Grill/@40.4229005,-86.9078096,17z/data=!3m1!4b1!4m6!3m5!1s0x8812e373c4bc8363:0x1df2c0530eee7a7a!8m2!3d40.4229005!4d-86.9078096!16s%2Fg%2F11hkfkjj_g', - website: 'https://www.halasgrill.com/' - }, - { - name: 'Five Guys', - description: 'Fast-food chain with made-to-order burgers, fries & hot dogs, milkshakes, and free peanuts while you wait.', - placeType: 'Food', - tags: [ 'Fast Food', 'American', 'Burgers', 'Fries', 'Milkshakes', 'Chain', 'Chauncey' ], - location: { type: 'Point', coordinates: [40.42343994609269, -86.90795109977412] }, - reviews: [ ], - images: ['https://tinyurl.com/fiveguysfood', 'https://tinyurl.com/5guysinsidewl'], - address: '135 S Chauncey Ave Suite 1-K, West Lafayette, IN 47906', - googleMap: 'https://www.google.com/maps/place/Five+Guys/@40.4233731,-86.9122599,17.05z/data=!4m6!3m5!1s0x8812e2aed99721e9:0x2a65fca44b4f0116!8m2!3d40.4233321!4d-86.9080151!16s%2Fg%2F1tvq4qs0', - website: 'https://restaurants.fiveguys.com/135-s-chauncey-avenue' - }, - { - name: 'Insomnia Cookies', - description: 'Bakery chain known for warm & fresh cookies, open late-night, and also selling ice cream.', - placeType: 'Food', - tags: ['Desserts', 'Cookies', 'Ice Cream', 'Open Late', 'Chain', 'On Campus'], - location: { type: 'Point', coordinates: [40.431694360504636, -86.91303583596788] }, - reviews: [ ], - images: ['https://tinyurl.com/insomniacookieslogo', 'https://tinyurl.com/insomniacookiespurdue'], - address: '602 W Stadium Ave, West Lafayette, IN 47906', - googleMap: 'https://www.google.com/maps/place/Insomnia+Cookies/@40.4315727,-86.9151089,17z/data=!4m15!1m8!3m7!1s0x8812fd4d4fe0373f:0x6ba1b40af4af0021!2sInsomnia+Cookies!8m2!3d40.4315727!4d-86.9130013!10e1!16s%2Fg%2F1vxw8wg_!3m5!1s0x8812fd4d4fe0373f:0x6ba1b40af4af0021!8m2!3d40.4315727!4d-86.9130013!16s%2Fg%2F1vxw8wg_', - website: 'https://insomniacookies.com/menu/17' - }, - { - name: 'Mad Mushroom', - description: 'Local pizza chain dishing up a wide variety of pies, grinders, pasta & salads. Most known for its Cheesestix.', - placeType: 'Food', - tags: [ 'Pizza', 'American', 'Italian', 'Local', 'Chain', 'Chauncey', 'On Campus', 'Open Late', 'Alcohol' ], - location: { type: 'Point', coordinates: [40.42426763341673, -86.90904218988186] }, - reviews: [ ], - images: ['https://tinyurl.com/madmushroomlogo', 'https://tinyurl.com/madmushpies'], - address: '320 W State St, West Lafayette, IN 47906', - googleMap: 'https://www.google.com/maps/place/Mad+Mushroom/@40.4241043,-86.9111746,17z/data=!3m1!4b1!4m6!3m5!1s0x8812fd4d1c8bf8cb:0xf26797ec22ddf82c!8m2!3d40.4241002!4d-86.9089859!16s%2Fg%2F12cpby27w', - website: 'https://www.madmushroom.com/west-lafayette' - }, - { - name: 'Maru Sushi', - description: 'Happening eatery serving up sushi & other traditional Japanese staples in a minuscule space.', - placeType: 'Food', - tags: [ 'Asian', 'Japanese', 'Sushi', 'Chauncey', 'Local' ], - location: { type: 'Point', coordinates: [40.42470168147317, -86.90665652715337] }, - reviews: [ ], - images: ['https://tinyurl.com/marusushilogopurdue', 'https://tinyurl.com/marusushipurduesushiplate'], - address: '102 N Chauncey Ave D, West Lafayette, IN 47906', - googleMap: 'https://www.google.com/maps/place/Maru+Sushi/@40.4245016,-86.9089847,17z/data=!3m1!4b1!4m6!3m5!1s0x8812e2a936645567:0xde255f15b5d68628!8m2!3d40.4245016!4d-86.906796!16s%2Fg%2F1vzg2vgk', - website: 'https://maru-sushi.us/' - }, - { - name: 'Bruno''s Pizza and Big O''s Sports Room', - description: 'American, Italian & some German dishes, plus a full bar, in a Swiss chalet-type setting.', - placeType: 'Food', - tags: [ 'Pizza', 'American', 'German', 'Italian', 'Alcohol', 'Local', 'Wabash Landing' ], - location: { type: 'Point', coordinates: [40.42252768794087, -86.90299580387695] }, - reviews: [ ], - images: ['https://tinyurl.com/brunoslogowl', 'https://tinyurl.com/brunospizzawlpizza', 'https://tinyurl.com/brunosdoughsplwl'], - address: '212 Brown St, West Lafayette, IN 47906', - googleMap: 'https://www.google.com/maps/place/Bruno''s+Pizza+and+Big+O''s+Sports+Room/@40.4223276,-86.9051094,17z/data=!4m15!1m8!3m7!1s0x8812e2a82517cf6d:0x81d1a879bb1aecda!2sBruno''s+Pizza+and+Big+O''s+Sports+Room!8m2!3d40.4223276!4d-86.9029207!10e1!16s%2Fg%2F1tgyx9kh!3m5!1s0x8812e2a82517cf6d:0x81d1a879bb1aecda!8m2!3d40.4223276!4d-86.9029207!16s%2Fg%2F1tgyx9kh', - website: 'http://brunodough.com/' - }, - { - name: 'Strings Ramen', - description: 'Restaurant with great ambiance offering Ramen as well as other Japanese side dishes.', - placeType: 'Food', - tags: [ 'Asian', 'Japanese', 'Ramen', 'Chauncey', 'Chain', 'Local' ], - location: { type: 'Point', coordinates: [40.42417961049075, -86.90706417318749] }, - reviews: [ ], - images: ['https://tinyurl.com/stringsramenlogo', 'https://tinyurl.com/stringsramenfood'], - address: '103 N Chauncey Ave, West Lafayette, IN 47906', - googleMap: 'https://www.google.com/maps/place/Strings+Ramen+Purdue/@40.4240367,-86.9092636,17z/data=!4m6!3m5!1s0x8812e3e71476fe81:0x489bc752b37b9cad!8m2!3d40.4240367!4d-86.9070749!16s%2Fg%2F11rwrz6c32', - website: 'https://www.stringsramen.com/' - }, - { - name: '', - description: '', - placeType: 'Food', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Food', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Food', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: 'Red Wok', - description: 'Chinese Food Place', - placeType: 'Food', - tags: [ 'Chinese', 'Asian', 'Open Late', 'Local', 'Chauncey' ], - location: { type: 'Point', coordinates: [ 40.42313730000001, -86.9087126 ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: 'Chipotle', - description: 'Mexican Food Place', - placeType: 'Food', - tags: [ 'Mexican', 'Healthy', 'Chain' ], - location: { type: 'Point', coordinates: [ 40.4236301, -86.9101227 ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: 'Silver Dipper', - description: 'Ice Cream Place', - placeType: 'Food', - tags: [ 'Ice Cream', 'Desserts', 'Local', 'Wabash Landing' ], - location: { type: 'Point', coordinates: [ 40.4197746, -86.91205520000001 ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Cafe', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Cafe', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Cafe', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Cafe', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Cafe', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Cafe', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Cafe', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Study', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: 'WALC', - description: 'Library', - placeType: 'Study', - tags: [ 'Library', 'Printers' ], - location: { type: 'Point', coordinates: [ 40.4276319, -86.91326409999999 ] }, - reviews: [], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: '', - description: '', - placeType: 'Living', - tags: [ '' ], - location: { type: 'Point', coordinates: [ , ] }, - reviews: [ ], - images: [ ], - address: '', - googleMap: '', - website: '' - }, - { - name: 'Hillenbrand Hall', - description: 'Residence Hall', - placeType: 'Living', - tags: [ 'Learning Community', 'Dining Court' ], - location: { - type: 'Point', - coordinates: [ 40.42669962268096, -86.92667082832517 ] - }, - reviews: [], - images: [ ], - address: '', - googleMap: '', - website: '' - }, -]) \ No newline at end of file diff --git a/app.js b/app.js index a56269b95..86b6a5219 100644 --- a/app.js +++ b/app.js @@ -123,6 +123,14 @@ const placeSchema = new Schema( type: String, required: true, }, + hours: [{ + type: String, + required: true, + }], + phone: { + type: String, + required: true, + }, placeType: { type: String, required: true, From 40f5903baad73307505ccf83d4a67ec4ed7d33f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Mar 2023 22:37:40 -0500 Subject: [PATCH 48/93] Minor additions to endpoint for retrieving specific place --- app.js | 4 +- package-lock.json | 184 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 +- 3 files changed, 188 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 86b6a5219..03aa4d7f3 100644 --- a/app.js +++ b/app.js @@ -358,12 +358,14 @@ app.get('/places/:id', async (req, res) => { suggestedPlaces.push(...matchingPlaceTypes); } + const hours = place.hours; + const phone = place.phone; const website = place.website; const address = place.address; const googleMap = place.googleMap; // sending everything as response - const data = { place, reviewRatings, averageRating, suggestedPlaces, website, address, googleMap }; + const data = { place, reviewRatings, averageRating, suggestedPlaces, hours, phone, website, address, googleMap }; res.send(data) //res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); } catch (error) { diff --git a/package-lock.json b/package-lock.json index 570d87416..42f68d011 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,8 @@ "passport": "^0.6.0", "passport-google-oauth20": "^2.0.0", "passport-local": "^1.0.0", - "passport-local-mongoose": "^7.1.2" + "passport-local-mongoose": "^7.1.2", + "socket.io": "^4.6.1" } }, "node_modules/@aws-crypto/ie11-detection": { @@ -1176,6 +1177,24 @@ "node": "6.* || 8.* || >=10.*" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "18.13.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", @@ -1337,6 +1356,14 @@ } ] }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, "node_modules/base64url": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", @@ -1748,6 +1775,63 @@ "node": ">= 0.8" } }, + "node_modules/engine.io": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.1.tgz", + "integrity": "sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3241,6 +3325,84 @@ "npm": ">= 3.0.0" } }, + "node_modules/socket.io": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", + "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.4.1", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/socks": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", @@ -3492,6 +3654,26 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index ebbb8c187..c63587e35 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "passport": "^0.6.0", "passport-google-oauth20": "^2.0.0", "passport-local": "^1.0.0", - "passport-local-mongoose": "^7.1.2" + "passport-local-mongoose": "^7.1.2", + "socket.io": "^4.6.1" } } From 94f957d2ff839189d579a573427db3bd07011e94 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Mar 2023 18:04:34 -0500 Subject: [PATCH 49/93] Specific place endpoint now returns reviews --- app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 03aa4d7f3..102e0647d 100644 --- a/app.js +++ b/app.js @@ -359,13 +359,14 @@ app.get('/places/:id', async (req, res) => { } const hours = place.hours; - const phone = place.phone; + const phone = place.phone; const website = place.website; const address = place.address; const googleMap = place.googleMap; + const reviews = place.reviews; // sending everything as response - const data = { place, reviewRatings, averageRating, suggestedPlaces, hours, phone, website, address, googleMap }; + const data = { place, reviewRatings, averageRating, suggestedPlaces, hours, phone, website, address, googleMap, reviews }; res.send(data) //res.render('place-details', { place: place, averageRating: averageRating, numRatings: reviewRatings.length }); } catch (error) { From c92a8b07d013b2faf13d0a0c79c790a2cb237819 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Sat, 11 Mar 2023 19:59:16 -0500 Subject: [PATCH 50/93] added verification check for purdue.edu emails --- app.js | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 102e0647d..452ca9d4e 100644 --- a/app.js +++ b/app.js @@ -267,7 +267,6 @@ function(accessToken, refreshToken, profile, cb) { app.get('/users', async (req, res) => { try { const users = await User.find(); - res.json(users); } catch (err) { console.error(err); @@ -678,10 +677,47 @@ app.post('/register', function (req, res) { console.log("Password length is less than 6!"); res.status(500).send('Password length is less than 6!'); } + if (req.body.username.endsWith('@purdue.edu')) { + const link = `http://localhost:3000/verify-user/${req.body.name}/${req.body.username}/${md5(req.body.password)}`; + const msg = { + from: '"Team AllPurdue" allpurdue2023@gmail.com', + to: req.body.username, + subject: 'AllPurdue Email Verification', + text: `Hello from AllPurdue! Boiler Up! Please click the link to verify your email:\n${link}.\n` + } + transporter.sendMail(msg, function(error, info){ + if (error) { + console.log(error); + } else { + console.log('Email sent: ' + info.response); + } + }); + res.render('home'); + } else { + const newUser = new User({ + name: req.body.name, + email: req.body.username, + password: md5(req.body.password) + }); + newUser.save(function (err) { + if (err) { + console.log(err); + res.status(500).send('Unsuccessful registration'); + } else { + console.log("User Successfully Registered!"); + res.render("login"); + } + }); + } +}); + +app.get("/verify-user/:name/:email/:password", function(req, res) { + console.log("User Successfully Verified!"); + const { name, email, password } = req.params; const newUser = new User({ - name: req.body.name, - email: req.body.username, - password: md5(req.body.password) + name: name, + email: email, + password: password }); newUser.save(function (err) { if (err) { From 9789b05e649c618a7b348442647b43e80bed86d4 Mon Sep 17 00:00:00 2001 From: Pramey Kabra Date: Sun, 12 Mar 2023 14:49:06 -0400 Subject: [PATCH 51/93] Major: Add Blog Functionality Working Condition - Get all blogs, View Indiv. Blog, Create Blog, Delete Blog, Links to Places in Blogs NOTE to FE Team: Similar to reviews, I don't verify the user is logged in or not. You should be able to handle it just like reviews. Remaining: Photos, Save/Unsave, Like/Unlike --- app.js | 145 ++++++++++++++++++++++++++++++++++++++++++++- views/blog.ejs | 19 ++++++ views/blogs.ejs | 27 +++++++++ views/new-blog.ejs | 38 ++++++++++++ 4 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 views/blog.ejs create mode 100644 views/blogs.ejs create mode 100644 views/new-blog.ejs diff --git a/app.js b/app.js index 452ca9d4e..924ded4b5 100644 --- a/app.js +++ b/app.js @@ -31,7 +31,7 @@ mongoose.set('strictQuery', false); // mongoose.connect("mongodb://localhost:27017/allPurdueDB"); // for windows -mongoose.connect("mongodb://127.0.0.1:27017/allPurdueDB"); + mongoose.connect("mongodb://127.0.0.1:27017/allPurdueDB"); const transporter = nodemailer.createTransport({ service: 'gmail', @@ -228,6 +228,46 @@ const reviewSchema = new Schema( const Review = new mongoose.model("Review", reviewSchema); + +// Blogs Schema + +const blogSchema = new Schema( + { + title: { + type: String, + required: true, + }, + text: { + type: String, + }, + place: { + type: Schema.Types.ObjectId, + ref: 'Place', + }, + author: { + type: Schema.Types.ObjectId, + ref: 'User', + required: true, + }, + images: [ + { + type: String, + }, + ], + likes: { + type: Number, + default: 0, + }, + likes_by: [{ + type: Schema.Types.ObjectId, + ref: 'User', + }] + }, + { timestamps: true } +); + +Blog = new mongoose.model("Blog", blogSchema); + /* ---------- [End] Models ---------- */ /* ---------- [Start] Google Auth ---------- */ @@ -637,6 +677,109 @@ app.post('/reviews/:reviewId/like/:userId', async (req, res) => { /* ---------- [End] Reviews Routes ---------- */ +/* ---------- [Start] Blogs Routes ---------- */ + +// GET all blogs +app.get('/blogs', async (req, res) => { + try { + const blogs = await Blog.find().populate(['author' , 'place']) + res.render('blogs', { blogs }); + } catch (err) { + console.log(err); + res.send('Error retrieving blogs'); + } +}); + +// GET new blog form +app.get('/blogs/new-blog', async (req, res) => { + try { + const users = await User.find(); + const place = await Place.find(); + res.render('new-blog', { users, place }); + } catch (err) { + console.log(err); + res.send('Error retrieving new blog form'); + } +}); + +// POST new blog +app.post('/blogs', async (req, res) => { + try { + const blog = new Blog({ + title: req.body.title, + text: req.body.text, + author: req.body.author, + place: req.body.place, + }); + await blog.save(); + res.redirect('/blogs'); + } catch (err) { + console.log(err); + res.send('Error creating new blog'); + } +}); + +// GET specific blog by ID +app.get('/blogs/:id', async (req, res) => { + try { + const blog = await Blog.findById(req.params.id).populate(['author' , 'place']) + res.render('blog', { blog }); + } catch (err) { + console.log(err); + res.send('Error retrieving blog'); + } +}); + +// DELETE specific blog by ID +app.delete('/blogs/:id', async (req, res) => { + try { + await Blog.findByIdAndDelete(req.params.id); + res.redirect('/blogs'); + } catch (err) { + console.log(err); + res.send('Error deleting blog'); + } +}); + +// GET recent blogs +// app.get('/recent-blogs', async (req, res) => { +// try { +// const recentBlogs = await Blog.find({}) +// // .populate('place', 'name tags placeType images') +// // @Andrew / @Antony Add Whatever You Need In this Populate Command ^ +// .sort({ updatedAt: -1 }) +// .exec() + +// // sending recentBlogs as response +// res.send(recentBlogs) +// } catch (error) { +// console.error(error); +// res.status(500).send('Internal Server Error'); +// } +// }) + +// PUT update an existing blog by ID +// app.put("/blogs/:blogId", async (req, res) => { +// const { blogId } = req.params; +// const { title, text, places } = req.body; +// try { +// const blog = await Blog.findByIdAndUpdate( +// blogId, +// { title, text, places }, +// { new: true } +// ); +// if (!blog) { +// return res.status(404).json({ message: "Blog not found" }); +// } +// res.json(blog); +// } catch (error) { +// console.error(error); +// res.status(500).json({ message: "Server Error" }); +// } +// }); + +/* ---------- [End] Blogs Routes ----------- */ + /* ---------- [Start] Login/Register/Home/Forgot Password Routes ---------- */ // GET Route for Homes diff --git a/views/blog.ejs b/views/blog.ejs new file mode 100644 index 000000000..11239c7b7 --- /dev/null +++ b/views/blog.ejs @@ -0,0 +1,19 @@ + + + + + + <%= blog.title %> + + +

<%= blog.title %>

+

<%= blog.text %>

+

<%= blog.place.name %>: View Place

+

Author: <%= blog.author.name %>

+

Likes: <%= blog.likes %>

+
+ + + All Blogs + + diff --git a/views/blogs.ejs b/views/blogs.ejs new file mode 100644 index 000000000..05d7b8ae6 --- /dev/null +++ b/views/blogs.ejs @@ -0,0 +1,27 @@ + + + + + + All Blogs + + +

All Blogs

+
    + <% blogs.forEach(function(blog) { %> +
  • +

    <%= blog.title %>

    +

    <%= blog.text %>

    +

    <%= blog.place.name %>: View Place

    +

    Author: <%= blog.author.name %>

    +

    Likes: <%= blog.likes %>

    + View + + +
  • + + <% }) %> +
+ New Blog + + diff --git a/views/new-blog.ejs b/views/new-blog.ejs new file mode 100644 index 000000000..a1168a31c --- /dev/null +++ b/views/new-blog.ejs @@ -0,0 +1,38 @@ + + + + + + New Blog + + +

New Blog

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + From 0bb0cd74a11170615cbe86407e6d5b4bf417e126 Mon Sep 17 00:00:00 2001 From: raseshr Date: Tue, 21 Mar 2023 19:17:16 -0400 Subject: [PATCH 52/93] Added backend routes for admin adding new place --- app.js | 42 ++++++++++++++++++++++++++ views/add_place.ejs | 73 ++++++++++++++++++++++++++++++++------------- 2 files changed, 95 insertions(+), 20 deletions(-) diff --git a/app.js b/app.js index 924ded4b5..c307ad188 100644 --- a/app.js +++ b/app.js @@ -328,6 +328,7 @@ app.get('/users/:id', async (req, res) => { /* ---------- [Start] Place Routes ---------- */ +/** app.get('/add_place', (req, res) => { res.render("add_place"); }); @@ -357,6 +358,7 @@ app.post('/add_place', async (req, res) => { res.status(500).send('Error adding place'); } }); +*/ // GET route for displaying all places app.get('/places', async (req, res) => { @@ -677,6 +679,46 @@ app.post('/reviews/:reviewId/like/:userId', async (req, res) => { /* ---------- [End] Reviews Routes ---------- */ +/* ---------- [Start] Admin Modification Routes ---------- */ + +app.get('/admin/add-place', async (req, res) => { + try { + res.render('add-place'); // render the add-place EJS view + } catch (err) { + console.log(err); + res.send('Error fetching add place form.') + } +}); + +app.post('/add', async (req, res) => { + try { + const newPlace = new Place({ + name: req.body.name, + description: req.body.description, + placeType: req.body.placeType, + hours: req.body.hours.split(','), + phone: req.body.phone, + tags: req.body.tags.split(','), + location: { + type: "Point", + coordinates: [req.body.longitude, req.body.latitude], + }, + images: req.body.images.split(','), + address: req.body.address, + googleMap: req.body.googleMap, + website: req.body.website + }); + await newPlace.save(); + res.redirect('/places/$(newPlace._id)') + } catch (err) { + console.log(err); + res.send("Error adding new place"); + } +}); + +/* ---------- [End] Admin Modification Routes ---------- */ + + /* ---------- [Start] Blogs Routes ---------- */ // GET all blogs diff --git a/views/add_place.ejs b/views/add_place.ejs index 78af8affe..3ec42d29e 100644 --- a/views/add_place.ejs +++ b/views/add_place.ejs @@ -1,29 +1,62 @@ - + - + + Add New Place

Add New Place

-
- - -
- - -
- - -
- - -
- - -
- - + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
From 0d3ab522359ed5724ae49e587c04350e9832098e Mon Sep 17 00:00:00 2001 From: raseshr Date: Wed, 22 Mar 2023 15:52:05 -0400 Subject: [PATCH 53/93] Added edit place by admin backend functionality --- app.js | 45 ++++++++++++++++++++++++++++++-- views/add_place.ejs | 2 +- views/edit_place.ejs | 62 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 views/edit_place.ejs diff --git a/app.js b/app.js index c307ad188..4bcf53c74 100644 --- a/app.js +++ b/app.js @@ -690,7 +690,7 @@ app.get('/admin/add-place', async (req, res) => { } }); -app.post('/add', async (req, res) => { +app.post('/admin/add-place', async (req, res) => { try { const newPlace = new Place({ name: req.body.name, @@ -709,13 +709,54 @@ app.post('/add', async (req, res) => { website: req.body.website }); await newPlace.save(); - res.redirect('/places/$(newPlace._id)') + res.redirect(`/places/${newPlace._id}`); } catch (err) { console.log(err); res.send("Error adding new place"); } }); +// GET request to display the form to update a place +app.get('/places/:id/edit', async (req, res) => { + try { + const place = await Place.findById(req.params.id); + res.render('edit_place', { place }); + } catch (err) { + console.error(err); + res.send('Error getting edit place form'); + } +}); + +// PUT request to update a place +app.put('/places/:id/edit', async (req, res) => { + try { + const place = await Place.findById(req.params.id); + if (!place) { + return res.status(404).send('Place not found'); + } + place.name = req.body.name; + place.description = req.body.description; + place.hours = req.body.hours; + place.phone = req.body.phone; + place.placeType = req.body.placeType; + place.tags = req.body.tags; + place.location = { + type: 'Point', + coordinates: [req.body.lng, req.body.lat], + }; + place.images = req.body.images; + place.address = req.body.address; + place.googleMap = req.body.googleMap; + place.website = req.body.website; + await place.save(); + res.redirect(`/places/${place._id}`); + } catch (err) { + console.error(err); + res.send('Error editing place information'); + } +}); + + /* ---------- [End] Admin Modification Routes ---------- */ diff --git a/views/add_place.ejs b/views/add_place.ejs index 3ec42d29e..903c625de 100644 --- a/views/add_place.ejs +++ b/views/add_place.ejs @@ -7,7 +7,7 @@

Add New Place

-
+
diff --git a/views/edit_place.ejs b/views/edit_place.ejs new file mode 100644 index 000000000..0d06e0cd3 --- /dev/null +++ b/views/edit_place.ejs @@ -0,0 +1,62 @@ + + + + + + Edit Place + + +

Edit Place

+ +
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+ + + + From a384dd885bce9dda2350a38a887a1510c05972dc Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 22 Mar 2023 16:02:17 -0700 Subject: [PATCH 54/93] major: add photos functionality to blogs --- app.js | 36 +++++++++++- package-lock.json | 141 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 + views/new-blog.ejs | 8 ++- 4 files changed, 182 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index 924ded4b5..5f18a407e 100644 --- a/app.js +++ b/app.js @@ -12,6 +12,9 @@ const passport = require("passport"); const GoogleStrategy = require('passport-google-oauth20').Strategy; const findOrCreate = require('mongoose-findorcreate'); const methodOverride = require('method-override'); +const multer = require('multer') +const path = require('path'); +const fs = require('fs'); const app = express(); @@ -23,6 +26,22 @@ const corsOptions ={ optionSuccessStatus:200, } +/* Multer Setup for Images */ + +var storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, 'uploads/') + }, + filename: function (req, file, cb) { + console.log(file); + cb(null, file.originalname); + } +}) + +var upload = multer({ storage: storage }) + +/* End multer Setup for Images */ + app.use(cors(corsOptions)); mongoose.set('strictQuery', false); @@ -47,6 +66,8 @@ const transporter = nodemailer.createTransport({ app.use(methodOverride('_method')); app.use(express.static("public")); +app.use(express.static("uploads")); + app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); @@ -695,7 +716,7 @@ app.get('/blogs/new-blog', async (req, res) => { try { const users = await User.find(); const place = await Place.find(); - res.render('new-blog', { users, place }); + res.render('new-blog', { users, place}); } catch (err) { console.log(err); res.send('Error retrieving new blog form'); @@ -703,16 +724,25 @@ app.get('/blogs/new-blog', async (req, res) => { }); // POST new blog -app.post('/blogs', async (req, res) => { +app.post('/blogs', upload.array('blog-images'), async (req, res) => { try { + var img = []; + for(var i = 0; i < req.files.length; i++) { + var unique = Math.random(); + fs.renameSync(req.files[i].path, req.files[i].path.replace(req.files[i].originalname, unique + "-" + req.files[i].originalname)); + var imgTitle = unique + "-" + req.files[i].originalname; + img.push(imgTitle); + } const blog = new Blog({ title: req.body.title, text: req.body.text, author: req.body.author, place: req.body.place, + images: img }); await blog.save(); - res.redirect('/blogs'); + res.send("Blog Uploaded"); + // res.redirect('/blogs'); } catch (err) { console.log(err); res.send('Error creating new blog'); diff --git a/package-lock.json b/package-lock.json index 42f68d011..0dc845a3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,12 +16,14 @@ "ejs": "^3.1.8", "express": "^4.18.2", "express-session": "^1.17.3", + "fs": "^0.0.1-security", "jsonwebtoken": "^9.0.0", "md5": "^2.3.0", "method-override": "^3.0.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", "mongoose-findorcreate": "^3.0.0", + "multer": "^1.4.5-lts.1", "nodemailer": "^6.9.1", "nodemon": "^2.0.20", "passport": "^0.6.0", @@ -1297,6 +1299,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -1494,6 +1501,22 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1619,6 +1642,47 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -1656,6 +1720,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -2057,6 +2126,11 @@ "node": ">= 0.6" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -2365,6 +2439,11 @@ "node": ">=0.12.0" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/jake": { "version": "10.8.5", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", @@ -2600,6 +2679,14 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", @@ -2775,6 +2862,34 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -3058,6 +3173,11 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3433,6 +3553,14 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3557,6 +3685,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -3674,6 +3807,14 @@ } } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index c63587e35..4b7ad21c4 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,14 @@ "ejs": "^3.1.8", "express": "^4.18.2", "express-session": "^1.17.3", + "fs": "^0.0.1-security", "jsonwebtoken": "^9.0.0", "md5": "^2.3.0", "method-override": "^3.0.0", "mongoose": "^6.9.1", "mongoose-encryption": "^2.1.2", "mongoose-findorcreate": "^3.0.0", + "multer": "^1.4.5-lts.1", "nodemailer": "^6.9.1", "nodemon": "^2.0.20", "passport": "^0.6.0", diff --git a/views/new-blog.ejs b/views/new-blog.ejs index a1168a31c..ccf99b3db 100644 --- a/views/new-blog.ejs +++ b/views/new-blog.ejs @@ -7,7 +7,7 @@

New Blog

-
+
@@ -32,7 +32,11 @@ <% }) %>
- +
+ + +
+
From b722a816007e3fcc5285b4f9e77e12996819b31b Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 22 Mar 2023 16:07:36 -0700 Subject: [PATCH 55/93] minor: added upload limits --- app.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 5f18a407e..f8c4d7cf4 100644 --- a/app.js +++ b/app.js @@ -38,7 +38,12 @@ var storage = multer.diskStorage({ } }) -var upload = multer({ storage: storage }) +var upload = multer({ + storage: storage, + limits: { + fileSize: 1024 * 1024 + } +}) /* End multer Setup for Images */ From d0e127332a16a124fe1dcabd3a62a25ff27f87d5 Mon Sep 17 00:00:00 2001 From: raseshr Date: Wed, 22 Mar 2023 19:13:08 -0400 Subject: [PATCH 56/93] Added delete place backend functionality --- app.js | 36 ++++++++++++++++++++++++++--------- views/add_place.ejs | 2 +- views/edit_delete_options.ejs | 19 ++++++++++++++++++ views/edit_place.ejs | 10 ++++++++-- 4 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 views/edit_delete_options.ejs diff --git a/app.js b/app.js index 4bcf53c74..2b0907301 100644 --- a/app.js +++ b/app.js @@ -696,9 +696,9 @@ app.post('/admin/add-place', async (req, res) => { name: req.body.name, description: req.body.description, placeType: req.body.placeType, - hours: req.body.hours.split(','), + hours: req.body.hours.split(',').map(tag => tag.trim()), phone: req.body.phone, - tags: req.body.tags.split(','), + tags: req.body.tags.split(',').map(image => image.trim()), location: { type: "Point", coordinates: [req.body.longitude, req.body.latitude], @@ -709,7 +709,7 @@ app.post('/admin/add-place', async (req, res) => { website: req.body.website }); await newPlace.save(); - res.redirect(`/places/${newPlace._id}`); + res.redirect(`/admin/places/${newPlace._id}`); } catch (err) { console.log(err); res.send("Error adding new place"); @@ -717,10 +717,13 @@ app.post('/admin/add-place', async (req, res) => { }); // GET request to display the form to update a place -app.get('/places/:id/edit', async (req, res) => { +app.get('/admin/places/:id/edit', async (req, res) => { try { const place = await Place.findById(req.params.id); - res.render('edit_place', { place }); + if (!place) { + return res.status(404).send('Place not found'); + } + res.render('/admin/places/:id/edit', { place }); } catch (err) { console.error(err); res.send('Error getting edit place form'); @@ -728,7 +731,7 @@ app.get('/places/:id/edit', async (req, res) => { }); // PUT request to update a place -app.put('/places/:id/edit', async (req, res) => { +app.put('/admin/places/:id/edit', async (req, res) => { try { const place = await Place.findById(req.params.id); if (!place) { @@ -739,23 +742,38 @@ app.put('/places/:id/edit', async (req, res) => { place.hours = req.body.hours; place.phone = req.body.phone; place.placeType = req.body.placeType; - place.tags = req.body.tags; + place.tags = req.body.tags.split(',').map(tag => tag.trim()); place.location = { type: 'Point', coordinates: [req.body.lng, req.body.lat], }; - place.images = req.body.images; + place.images = req.body.images.split(',').map(image => image.trim()); place.address = req.body.address; place.googleMap = req.body.googleMap; place.website = req.body.website; await place.save(); - res.redirect(`/places/${place._id}`); + res.redirect(`/admin/places/${place._id}`); } catch (err) { console.error(err); res.send('Error editing place information'); } }); +// DELETE a place by ID +app.delete('/admin/places/:id', async (req, res) => { + try { + const place = await Place.findById(req.params.id); + if (!place) { + return res.status(404).send('Place not found'); + } + await Place.findByIdAndDelete(req.params.id); + res.redirect('/places'); + } catch (err) { + console.error(err); + res.send('Error Deleting Place'); + } +}); + /* ---------- [End] Admin Modification Routes ---------- */ diff --git a/views/add_place.ejs b/views/add_place.ejs index 903c625de..72bbf118d 100644 --- a/views/add_place.ejs +++ b/views/add_place.ejs @@ -7,7 +7,7 @@

Add New Place

-
+
diff --git a/views/edit_delete_options.ejs b/views/edit_delete_options.ejs new file mode 100644 index 000000000..c44c3e5a6 --- /dev/null +++ b/views/edit_delete_options.ejs @@ -0,0 +1,19 @@ +
+

<%= place.name %>

+

<%= place.description %>

+ Edit +
+ +<% places.forEach(place => { %> +
+

<%= place.name %>

+

<%= place.description %>

+ + + +
+ +
+
+<% }); %> + \ No newline at end of file diff --git a/views/edit_place.ejs b/views/edit_place.ejs index 0d06e0cd3..6adf3242d 100644 --- a/views/edit_place.ejs +++ b/views/edit_place.ejs @@ -7,7 +7,7 @@

Edit Place

-
+

@@ -26,6 +26,12 @@
+
@@ -56,7 +62,7 @@
- +
From 37bbde7efc6a2c327f0d0a58d10a9576726bbcde Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 22 Mar 2023 16:22:22 -0700 Subject: [PATCH 57/93] added saved blog field to user schema --- app.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app.js b/app.js index f8c4d7cf4..04f3ca4fc 100644 --- a/app.js +++ b/app.js @@ -113,6 +113,10 @@ const userSchema = new Schema( type: Schema.Types.ObjectId, ref: 'Review', }], + savedBlogs: [{ + type: Schema.Types.ObjectId, + ref: 'Blog', + }], googleId: { type: String } From 0a29b9ac71a593be599da5aa02bef0b1fa015b09 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 22 Mar 2023 17:45:49 -0700 Subject: [PATCH 58/93] major: added saved blogs functionality --- app.js | 46 ++++++++++++++++++++++++++++++++++++++++++++-- views/blog.ejs | 5 ++++- views/new-blog.ejs | 2 +- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 04f3ca4fc..24e0ed30a 100644 --- a/app.js +++ b/app.js @@ -750,8 +750,7 @@ app.post('/blogs', upload.array('blog-images'), async (req, res) => { images: img }); await blog.save(); - res.send("Blog Uploaded"); - // res.redirect('/blogs'); + res.redirect('/blogs'); } catch (err) { console.log(err); res.send('Error creating new blog'); @@ -780,6 +779,48 @@ app.delete('/blogs/:id', async (req, res) => { } }); +// Save specific blog by ID +app.post('/save-blog/:id', async (req, res) => { + try { + if (!currentUser) { + res.send("no user logged in"); + return; + } + if (currentUser.savedBlogs.includes(req.params.id)) { + res.send("blog already saved"); + return; + } + currentUser.savedBlogs.push(req.params.id); + User.findOneAndUpdate( + { _id: currentUser._id }, + { savedBlogs: currentUser.savedBlogs }, function (err) { + if (err) { + console.log(err); + res.sendStatus(500); + } else { + res.status(201).send("success") + } + }); + } catch (err) { + console.log(err); + res.send('Error saving blogs'); + } +}); + +// Get saved blogs of the current user +app.get('/saved-blogs/', async (req, res) => { + try { + if (!currentUser) { + res.send('user not logged in'); + return; + } + res.send(currentUser.savedBlogs); + } catch (err) { + console.log(err); + res.send('Error sending saved blogs'); + } +}); + // GET recent blogs // app.get('/recent-blogs', async (req, res) => { // try { @@ -858,6 +899,7 @@ app.post('/register', function (req, res) { if(req.body.password.length < 6) { console.log("Password length is less than 6!"); res.status(500).send('Password length is less than 6!'); + return; } if (req.body.username.endsWith('@purdue.edu')) { const link = `http://localhost:3000/verify-user/${req.body.name}/${req.body.username}/${md5(req.body.password)}`; diff --git a/views/blog.ejs b/views/blog.ejs index 11239c7b7..bd3398d44 100644 --- a/views/blog.ejs +++ b/views/blog.ejs @@ -13,7 +13,10 @@

Likes: <%= blog.likes %>

- +
+
+ +
All Blogs diff --git a/views/new-blog.ejs b/views/new-blog.ejs index ccf99b3db..e58c3aff7 100644 --- a/views/new-blog.ejs +++ b/views/new-blog.ejs @@ -34,7 +34,7 @@
- +
From 28bd5a5eb8816157f6f110377af1ca578598b2c2 Mon Sep 17 00:00:00 2001 From: yashnarain Date: Wed, 22 Mar 2023 18:01:00 -0700 Subject: [PATCH 59/93] major: added delete for photos when deleting blogs --- app.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app.js b/app.js index 24e0ed30a..d42b74166 100644 --- a/app.js +++ b/app.js @@ -771,6 +771,14 @@ app.get('/blogs/:id', async (req, res) => { // DELETE specific blog by ID app.delete('/blogs/:id', async (req, res) => { try { + const blog = await Blog.findById(req.params.id); + var img = blog.images; + for(var i = 0; i < img.length; i++) { + var path = "uploads/" + img[i]; + fs.unlink(path, (err) => { + if (err) throw err; + }); + } await Blog.findByIdAndDelete(req.params.id); res.redirect('/blogs'); } catch (err) { From fde7401e0f5bed143473d117e22bba6791b0bc7a Mon Sep 17 00:00:00 2001 From: raseshr Date: Thu, 23 Mar 2023 17:59:03 -0400 Subject: [PATCH 60/93] minor changes to add and edit place by admin --- app.js | 6 ++++-- views/edit_delete_options.ejs | 19 ------------------- views/edit_place.ejs | 3 +-- 3 files changed, 5 insertions(+), 23 deletions(-) delete mode 100644 views/edit_delete_options.ejs diff --git a/app.js b/app.js index 2b0907301..64aab5f81 100644 --- a/app.js +++ b/app.js @@ -681,15 +681,17 @@ app.post('/reviews/:reviewId/like/:userId', async (req, res) => { /* ---------- [Start] Admin Modification Routes ---------- */ +//Get request to display add place form app.get('/admin/add-place', async (req, res) => { try { - res.render('add-place'); // render the add-place EJS view + res.render('add_place'); // render the add-place EJS view } catch (err) { console.log(err); res.send('Error fetching add place form.') } }); +//POST Route to add a place app.post('/admin/add-place', async (req, res) => { try { const newPlace = new Place({ @@ -723,7 +725,7 @@ app.get('/admin/places/:id/edit', async (req, res) => { if (!place) { return res.status(404).send('Place not found'); } - res.render('/admin/places/:id/edit', { place }); + res.render('edit_place', { place }); } catch (err) { console.error(err); res.send('Error getting edit place form'); diff --git a/views/edit_delete_options.ejs b/views/edit_delete_options.ejs deleted file mode 100644 index c44c3e5a6..000000000 --- a/views/edit_delete_options.ejs +++ /dev/null @@ -1,19 +0,0 @@ -
-

<%= place.name %>

-

<%= place.description %>

- Edit -
- -<% places.forEach(place => { %> -
-

<%= place.name %>

-

<%= place.description %>

-
- -
-
- -
-
-<% }); %> - \ No newline at end of file diff --git a/views/edit_place.ejs b/views/edit_place.ejs index 6adf3242d..f3922591f 100644 --- a/views/edit_place.ejs +++ b/views/edit_place.ejs @@ -32,7 +32,6 @@ -
@@ -60,7 +59,7 @@
-
+
From f9b6f31774c661b742cc0da5fcfee92023759e28 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Mar 2023 18:01:25 -0400 Subject: [PATCH 61/93] Blog schema takes tags instead of place and endpoint added to like and unlike a blog --- app.js | 193 +++++++++++++++++++++++++-------------------- uploads/meowdy.png | Bin 0 -> 12094 bytes views/blogs.ejs | 27 ------- 3 files changed, 109 insertions(+), 111 deletions(-) create mode 100644 uploads/meowdy.png delete mode 100644 views/blogs.ejs diff --git a/app.js b/app.js index d42b74166..5ea1249b6 100644 --- a/app.js +++ b/app.js @@ -262,38 +262,39 @@ const Review = new mongoose.model("Review", reviewSchema); // Blogs Schema const blogSchema = new Schema( - { - title: { + { + title: { + type: String, + required: true, + }, + text: { + type: String, + }, + tags: [ + { type: String, - required: true, }, - text: { + ], + author: { + type: Schema.Types.ObjectId, + ref: 'User', + required: true, + }, + images: [ + { type: String, }, - place: { - type: Schema.Types.ObjectId, - ref: 'Place', - }, - author: { - type: Schema.Types.ObjectId, - ref: 'User', - required: true, - }, - images: [ - { - type: String, - }, - ], - likes: { - type: Number, - default: 0, - }, - likes_by: [{ - type: Schema.Types.ObjectId, - ref: 'User', - }] + ], + likes: { + type: Number, + default: 0, }, - { timestamps: true } + likes_by: [{ + type: Schema.Types.ObjectId, + ref: 'User', + }], + }, + { timestamps: true } ); Blog = new mongoose.model("Blog", blogSchema); @@ -712,11 +713,10 @@ app.post('/reviews/:reviewId/like/:userId', async (req, res) => { // GET all blogs app.get('/blogs', async (req, res) => { try { - const blogs = await Blog.find().populate(['author' , 'place']) - res.render('blogs', { blogs }); + const blogs = await Blog.find(); + res.json(blogs); } catch (err) { - console.log(err); - res.send('Error retrieving blogs'); + res.status(500).json({ message: err.message }); } }); @@ -724,8 +724,7 @@ app.get('/blogs', async (req, res) => { app.get('/blogs/new-blog', async (req, res) => { try { const users = await User.find(); - const place = await Place.find(); - res.render('new-blog', { users, place}); + res.render('new-blog', { users }); } catch (err) { console.log(err); res.send('Error retrieving new blog form'); @@ -735,32 +734,23 @@ app.get('/blogs/new-blog', async (req, res) => { // POST new blog app.post('/blogs', upload.array('blog-images'), async (req, res) => { try { - var img = []; - for(var i = 0; i < req.files.length; i++) { - var unique = Math.random(); - fs.renameSync(req.files[i].path, req.files[i].path.replace(req.files[i].originalname, unique + "-" + req.files[i].originalname)); - var imgTitle = unique + "-" + req.files[i].originalname; - img.push(imgTitle); - } - const blog = new Blog({ - title: req.body.title, - text: req.body.text, - author: req.body.author, - place: req.body.place, - images: img - }); - await blog.save(); - res.redirect('/blogs'); + const { title, text, author, tags } = req.body; + const images = req.files.map((file) => file.filename); + + const newBlog = new Blog({ title, text, author, tags, images }); + const savedBlog = await newBlog.save(); + + res.status(201).json(savedBlog); } catch (err) { - console.log(err); - res.send('Error creating new blog'); + console.error(err); + res.status(500).send('Server error'); } }); // GET specific blog by ID app.get('/blogs/:id', async (req, res) => { try { - const blog = await Blog.findById(req.params.id).populate(['author' , 'place']) + const blog = await Blog.findById(req.params.id).populate('author'); res.render('blog', { blog }); } catch (err) { console.log(err); @@ -830,41 +820,76 @@ app.get('/saved-blogs/', async (req, res) => { }); // GET recent blogs -// app.get('/recent-blogs', async (req, res) => { -// try { -// const recentBlogs = await Blog.find({}) -// // .populate('place', 'name tags placeType images') -// // @Andrew / @Antony Add Whatever You Need In this Populate Command ^ -// .sort({ updatedAt: -1 }) -// .exec() +app.get('/recent-blogs', async (req, res) => { + try { + const recentBlogs = await Blog.find({}) + // .populate('place', 'name tags placeType images') + // @Andrew / @Antony Add Whatever You Need In this Populate Command ^ + .sort({ updatedAt: -1 }) + .exec() -// // sending recentBlogs as response -// res.send(recentBlogs) -// } catch (error) { -// console.error(error); -// res.status(500).send('Internal Server Error'); -// } -// }) + // sending recentBlogs as response + res.send(recentBlogs) + } catch (error) { + console.error(error); + res.status(500).send('Internal Server Error'); + } +}) // PUT update an existing blog by ID -// app.put("/blogs/:blogId", async (req, res) => { -// const { blogId } = req.params; -// const { title, text, places } = req.body; -// try { -// const blog = await Blog.findByIdAndUpdate( -// blogId, -// { title, text, places }, -// { new: true } -// ); -// if (!blog) { -// return res.status(404).json({ message: "Blog not found" }); -// } -// res.json(blog); -// } catch (error) { -// console.error(error); -// res.status(500).json({ message: "Server Error" }); -// } -// }); +app.put("/blogs/:blogId", async (req, res) => { + const { blogId } = req.params; + const { title, text, places } = req.body; + try { + const blog = await Blog.findByIdAndUpdate( + blogId, + { title, text, places }, + { new: true } + ); + if (!blog) { + return res.status(404).json({ message: "Blog not found" }); + } + res.json(blog); + } catch (error) { + console.error(error); + res.status(500).json({ message: "Server Error" }); + } +}); + +// Like and unlike a blog +app.post('/blogs/:blogId/like/:userId', async (req, res) => { + const blogId = req.params.blogId; + const user = await User.findById(req.params.userId); + + try { + const blog = await Blog.findById(blogId); + + if (!blog) { + return res.status(404).send('Blog not found'); + } + + const hasLiked = blog.likes_by.includes(user._id); + + if (hasLiked) { + blog.likes = blog.likes - 1; + blog.likes_by.pop(user._id); + // user.likedReviews.pop(review._id); + } else { + blog.likes = blog.likes + 1; + blog.likes_by.push(user._id); + // user.likedReviews.push(review._id); + } + + // Save the changes to the blog and user documents + await blog.save(); + // await user.save(); + + return res.json({ blog }); + } catch (error) { + console.log(error); + res.status(500).send('Server error'); + } +}); /* ---------- [End] Blogs Routes ----------- */ diff --git a/uploads/meowdy.png b/uploads/meowdy.png new file mode 100644 index 0000000000000000000000000000000000000000..0a398c7f8ce56ddcd24a876fa90f80fb4c6d5bc4 GIT binary patch literal 12094 zcmV-EFTv1>P)U#5g_nztZ`|V-nkG0Ra zRmEiBRlTBO0Nk{zrigmZk{d5I(9?&Vx> zXbkr|!a6Kxccp}T{OYS`-}B5f<(>J{-yQ3%3UL3<$3D=1+c$m36*f1&g_=JqrF?Kq z(|b}%*A%@}a(%Q`U23ULymvyyJEfG0h@)10(;L=WsSXse4-l_T;^dsW6Jmc)f~-To zxEmLXyItSiC}sNMVzzpzo1Z+lS#ED|>(=x=Pd}3YNbtS)dvl~zL+r89U$XTiN!g6@;2?EXus`j|*g`89sRc*FLPzR+zZI3ttP8>c4 zVh9>%v*crZJ1~(DJG_nxc>3v&g+Dp} z=wI63z4N`2b|38m{cgSC-rY5u&5lwES{3nvNFewCuHqEDfD?yvf{5Tn5btr$HK7-# zsW7IAk}KMN_n@>8!to1L@rVdr>`I*XXZ>P%bAEFAE30eQzVEd!4FB{iO$iR*>5qLZ zeC>C9^>>YTZhwE7HXppan$b((){UEN&i9PtNY;vTju0b)2QPT1^s`6|k*@2AT_nbc za}MVm;shTY!3RVFs>(QyoNd;eot-gF6KTqnTG8t4`C3s`9G(yY-bX^;ae8UBz4GWI ze{Z(B@+0dm{_OYs)gRbDY~ekK>>H!`Z!mIgLBfoLS80lvGJ6G#kqX>_$=CemGtxjM5sz3SduRQzgvwxt& z+3>&rm;c@qOv9g<#{D0vwUV>qYUS)~O^BYZ>*)I)=Y(+_nbJfp<>+ihJmLj)Vm4nL zxlCwPoH%ANn6s{xB0?@g2)?~mh%s`yTGIDD^ZCTt*_u%@DOFHmn-WqgK?Kuwiqo+9 zW~SBafBGuF2E6(Z<@ftuVSj%1%^md{(=hfqXKv0Z&nkkf#qDtDG{77 z?<3wpnWlc&Z@#HJoqvQs=nA;~rI-KOumSF5_Z_QdNiTwj0h>o;z`nkx6=Ud~^>pVxo=Q=j?+3Q`1i(%Hkc)7&qf8ekD zh0oWVUv$XJfAxo-x%-f1{-zc7`@JPZ*#w+RF=1#+l4~m`v}DPNnIj5_7p6SogCMde zIAQB|^sysGA^Jeyn^Uc|woo*+3|XkI5}f51>g~TGju7T_oh4$m7IynY&Y2Jb%lQHX z#xcrD6(trNl-}Y=L?pNJB zzqEUa+fP6HY3Tw`j3swhGun66unAvdNQ;IUB zOs!C}l5$~6g=xy9X(FY9YQ+Jw7>Pd61@i~uy@jd4qMlfU;dzW#Vn5Kj{4_dM6Mn!X$X&O({Fg&&0Z2xG^`D@kb*OPfNoa()A|GKA! zZ~2;4efD#=9!fsp|Lh-q|I@=TkyEBrEP+xJHUR1Yk7CKzA^vv`ob%MG)S{FEilPNj zrK&SOPzxm&QYlQy$_^pQv-QLW@OxnaM%62yNnrSXrYar)+<-ABZ)w*UIKeb<*i z^^3pwjw``^|DXQ`-R<`l=`^81v;X3#>c}aRvpGd^4(~%ty6iQz6mls9fi6UXw0CbA zE`U&*|EP!;qS%g?R;af6QFE|xEbN*2Gru7ch%qvo&FH#-^THGF`6|Bf{0qGL+6~K^ zla(}L?=5nZo}4RF&ZKJAX4WrIRd)NmRbr#(%464lel}bD@Ril2pX$3?QF1Y}RVtKR znNqPGUzC(HQ!0#8req~oGi9}%My(u6Ai)PfL1Dg_k*0}Zw?$l_kC840f&=fssRa!j zHh{B=F3ti9FOHlhhTZN7SEg?)dH1zR*73W(@sDi3;q<*{&%X51+j=Vew|?k}r&BIy zg=`TgrCL#}sDcPN7b@UHu)J1K*USTsQWb~oR_DE$BDMU%iMKZu0p}3RY?UTd6K+MF zZ|`mId-$u>2~HhV%?EU`Z>4Wj#(dt9OJTd-;ItwNQ9NQf8&K`^2ElnT-&HD#5}G1{ za|rk{rd1UGfzEe-j8dPRU+vGo@mHRI<=M9}g!SL@p~s#sIa6Akt`$%y2N4`>etSV} zN91rSN--1RRB`U`M>@_7F~a}T^->i^XHuRfhhKF0mkxu))x1-ptmHRoq9Ii3>5p|u@v z6esO;98Qw9jLubX;F`~XrVzvgY)|5l7KJJ5K)flyOos_yTqT4^2$mJcSqBQ^enb!? zh~*33l;FKbT7{MB@ZQ;TUYN&@=sm#;;w-vDVYeUIk7J+cbcqHrrb$6hNw2hU@&% zk(&ZrhwLqXUR8&y6`DiVDwJZ;lMnWK7X;tM_N|qitGxy>lh_GJL32S$r3+$lovMY$ z&JjW&pyYZ82!xUgXLs*?*irxT^5o>?&p!GcuROy~ed$3e!2j|0Tz$GWdF58auhq;- z<-#GmV`65z1a)XJ&!`F#;?XYCB9~e#-g#;%1m|ssdb8hVVk&~-c zR-ei_n?qL!-VtJl6HiW=&3>R%MO?*cp)}v5>PWdVrNop*oV53BelCc#$WCwwHJc6Y zx@dmHDZ@B*l>BvloL~L(-}H6A_T&HL*B@9mE!(6F)sa+~a*Jk)B~EWF%3T!8-n@=c zQYqA<+o;EejrD!y_d53l;&KxS`@Lmp7juBK&l{8szVzV1qZ+9f@ z#8d}|sHeQ4cLCV<%+_fOPVmlIV(7hjpIV4s=z`F79o~0{cxqJ_L-_X9vin#5>;Le( zXAevPxA%#4QuZm6N@X%r2`Wexi{J|OV7&lQh*k^pn!rjaZ)((7$ywg?VMjqC%^|l+ ztMZm4&*5CK-^1IFvmb5Wp;R+9`(a|5GQ*^d(;;Ma?dvx5g(%`3UG#WygmCx~qL+s3 zP&`T>q3;4g?307{lu}u*x8$6!RLVCz8U2+9rGRi}J+PQnPP)LNvoxMV1XA_F{vT@m z2VowdB@!;4YrEW%s1~&}b9Q(>G?;=%8EaUjq8uS$S z@&i%8K2=f~m~vz&k&`YkQ-^ed7lWM~GE@_|yip$(aJHSBOCdCSdg0J3!F#k=uUNIT z*Hyeo>m@rxDpa8ygmFAP6?KBAIa$$TAEBaD2m3rRmCOwAA)sX>I)99&Om~i`LT~^I zEl~qI*vmaU$T)smbm)Y__>hu=H&7BC-Cnc0p}e~&fzp1YCnh5 zC9RpGswkdag8RF~W=O17P*j^@E8=}S(0a`9wVkA+KXQWBV(5>0=rzD{Hph2?X|rLm zTmmrcCW#?jS@z-D15-e0$qQEAhgRiL0Zj?cTU1o6r0vAvQXyCHeaEf)BVW34#>{&v z0f~w)8EtJ+S|ViP3 zz(r9_sfXR>93{h0C(ibJPP(3D-!TiqqVseiG|38`6Od||D&Sg#V?AJhwA~_tNXyGw zw(1=CCV1yuv-NNOf`^DIqgE}=N)(|M$L4&`i#N|1Cq?_pIAz>C;Dc|GnZ1XY_FHSU z`L6akrB+;ZSVV1M^T99leWbL+u#`e6S#wG2FzX*!7#e0G=}>)U{LAyA5aiiLn&GnVme?O7Y~DrVEv6HvyF( z6VW?*5xNM=80n&?3ql_w9*bTAj_S?icqb&x#)=5ylp^+TI~hV!6TG1_6jh<%NEP;D zVl%ASj+ymX8H+=rM@xYyM?YkhlV;CDJfbw5D-^ZUCvQ*ySVV=0+KjVV<=)nDXS3scRQBq~MR9Ma`K|{aDqYFAvhtFax_EYq$N^9rZSeweyr?LVzxqXZyr@Oyp8f7wwB3oT@~sUgQAk9Mw6BnjhFt zg^)5qG9n&dw}^)z%{i+%;XZ_x1XZG!Bep2#N>xXyg`p&dtQ2)5g^F02!~srlnknPN zvQtiH9gE&7p21n0(~F=Y)RxhEFYR<4qA_Jk$$H!ko7%;`DaInZ%cm==J9*XO+zUUu z{^=VJO85X_)eG}}#z|GKtrooR>Ir8<;?~)YTjy)Gld?&LRFoGUQCvY{=@WILWwLkY)qCm;!w8phB&cR4Nhz)m>!NB8Q!s@uhIu z2~RzCg%3P_%Ch&wYB_|*k#aWs1`YVzVt%oV{1AQ7Hb)-Ot1Hfj!kzVwv)ztyQg&0ZvV*gPSxc~FrxtQM z83nQAO&vA!hI-H;1_#$l62S>hAvl{6$cLhz2vrZSv4l{l)Kc(Nf+&j)-h1VQ_gtE@ z@Q$Dc{&lW3`<;OcRL#&xfT_H>p5=Y8a9CP4u2vbYt;^?q)ac{QNz0GdTtD+5g%1#F zsyL@8#rm@nESC3<&U>!RBG=}^l;>>riL>3nK4o@OVaSzzO600ktpqWlDh*=Zig0fn z#IYSHR4sU?s5D1-h+N+AyW%Yt5EVQbuN5Dl_i(a^TwV1%d3nX66Qm|eGBc>&qpsq; zqdG%S9PGY0Gi6AH>QGHq?R8eo6$wn!gu2RXwxH{}vsCI&)LfrAf94nNKX3&UC&%d) zv{I_GEE4FPl5^&A6zDxy=aKs8DPw_M&TRLI-IUl3ne8~SpAzFVSw2x(RZ@I&Zi0$K zwcwplw6xgYL>@Tw1zL^YIrAF|F$l{T=)|$=1D97ltGQ<$g;{U}D&9jW7O&P)AvPfJ zF#>X}eDcP!iqdr*U{O#`g>l@YBCM7R?U#%3&e`UNY6w3zT>pj7Km9gLc82@AM2G<| zzEvP;Ek;Y_aiFy!)x4vS2mw}IfQ6^zo>VH^lo-auK2?U+T%WQsOxaEdx%mjJ;O8ph z1k{iUQq55Z9}x@)Jd2)1Fd;8y9W(D)&H{aaE}FxoS`;M?LKG{YIgTg}DTVB|HkV-^SRfa;lbMeqXO0$q*%>)8f|MoY%Wz<#@9y&LFa2h*M)a%@n{ zf@d-7@ZwPl-dPeAjVgt0=W^VWu=h1HSbN%t0RDi9&5zu;mC&K*W5L zcg1{FGf((tO4K!=z{Li&TGOHBX?37nOz3(*oVEV6hDgoIe!pinn-P6rx8GmCzTJQF z)!q50-%jBJgwMYCDy!9;<$Ol$X7pE=#8TO=&q%{a%@eaO(pAq?m8n!i5IAKyn-hH` z_()2L7)`JxXG`(5;Hp?Yp%y)fdSVP#5pKgsf9jKt!B2KtMfKO^emXtq3UY zw*-tFdJs7)DHZFaVI>FWo4Iv{F`aTEgq|++Dly(2_q!k4Ps88(oB!~Yv$tIVFWtG% zY&UQ+U$9&)Sk8OqeWbtoD1O+Jb_4tUj-e#xy_F`U+HiK-4TOgKskIQIr|+ZHhFXu+ zDfnPJ-8Z4sVnQ`rTVp_s{>%{gF?+{xiS!0`CBwg8Q2HKBiq4n9pV` z=5vBLR*M;@t0nV38d6{!$kT+D%yQln#37}SrvXj5%@(LRPoYIRO7wyGd`{;LP#e8# zWe3X*oPcU>^_bd<0u8OzmP9#r*34$Nq^jBQ>cHWT3p%s>+SH%x9{Kouf|;d@4xedCAWr*2{L%AnwDyvw^}R6p@-n#0vLFMuMhzT1=}cT8t7us<+3mRd^zlgVSRr) zd~u!951yZ|fAZs>`SR|a5~y%hv12^LqxcI=@Jqomz=(M|9t(wy}n-m zqu4E8e({z3;xnK7@&hZf{Vo&`nbJh5%8({H2VFm>)XH|ZMVxZ&(W`{eQ6;i(*=8Sl zVi$3JPl%o;zsmXqQVVI^Gj6x6@80FgG_l|B*q)zLbH)V^S{SP(a6(0#;$@<$GK-zT z%7aHd^uZcHH}9^Q&pP_$DGL$HoU0N;B$rIBxwR~|zSPN1s+mZ=M zsaaWXCs^D3op|VCM+lW5;C*axc)@uKbxTnut*GzO&Z*+kuwMVW+d6*si+}gCw;!_X z0SK1FcwC&3$cTiNS=!|Kem5{pnSO%Ve93;?v)Sz!hKZarvuM8I+SRK(@x(Q*U0pHn zJ%~qQkMBC12z@`}>g7}VXp@!VtzaiqQl8lFcBFA+x85=iJEmzOClhwcBf%LeVtuyZ z{QR8agvon$c{1=-(WZa{SA~5CjU8b=$9J8UX}DiDFa6wq@pnJ>uA#pP;v7}1IvIlP z8dW`_&T559=Kgx5)H~ceU$fcm8Ha?3Cj?LQo=YdEJbC>Qu3cU7{`Wn}mD5Yi7c*k? zcnMVTjKxa7v(D4c=fvpSz(v=h{7TJ6ZD3RTnNkv^+Dw3|W4jr7@#Qb^`pxUyym6cB zXKO1vIEVM1)oRgbbUIw@kuEUn7o;GCqA&bs53rf?AXb0?0+3p7_OJcO@ z=61j5d^fV*?$`|zAoSgw`N@fan}Q>WaQA%6`Su>ewC98Gdy2;&xrVG(EktyblF3e) z1SBOS3f>te^#HbVKDK6y;` zxO{qvlarnhJNns->OBHE=lbgpQ`o=R3h#UBDem9D&-#4BZojuksMYoNV`8)0bH3Rz zOqE;0Nv{?+IB^gsIo>;0BmpzA!U!njYQdmGeu^rxo=unoc3 zTypVFdEY~l^KZGrV^2QD>hzTJbF;0(ut!xnKiiP^BfD{8H>G1^ycBD$z)04@>FJ6; z{D(inqF-=!c8`}|`Xamimb>@QIaw}v{IN&SzO!Vjw8_ih+xV+xq_x2rZCxNHj%sl> z9l0M0pa1pe`Sd^ef4Ft`jM&YHvmW0X^Yd9`xtJl|TU1mM`>k0VA3VWT|IUi{cV6M@ z<;yIW6PGSsVwxUj7zUL|zT)%M_IolXU-+4sTMp>JzYN01H2HV7zcW=LyOh%^ANbB2si$9lWv`R88b`pw&h1ro<& z*B-@t&-(11%@HqG%$GeWC-!?GglN5jlt<0wryhcgf7=xG92mDw~U zybly#8x@)ZVuL$2JWsu#Gdn*&=e6r!X1m=oW=9okzAqLF)@S#CLvzWID{V6S{Aj%(gOfvB07&3a4D z*GZcZ(F#teSQ)^H61!j%hqbU=%{X11koISkVIYkYIaf+bXt0E=^8vxx{BJ3A6yRd~ z^)MfxZR$}%V3-DO-n_}(vwJqR=_1pZxqbUKP+9hU8=)0Ej+5oedK@B$?Av8mRu5I$ zzsU-QiTA|d3DJ_BE=E?18Bv~M%9VTf?y?_uq;U_`d_Ymfd5B(^bsn#k;9=SK%!7r6 zxm3o{PC`mO^ZC3bV9sD6D(09|L4)D*omk7z;V3Q~k}l~c|)TZUm`97hb-0Q0`*eeZn_%lVvIGrhltmW1!Tp$}qYxm@7G1xJuL>m5v! zVR5>yJMzhafvXfKB{59{-aF=to=2`-VYMoZso?t=^TpguTl6eva~6hC#5-+6fsRsf zIGMlj!k-ZM%)3Vc+6JYKjI}eSD_0R`f)kXhR~F3TQ(Qh-@#LeAaDKjFz1^~2uc_G} zh%p9E7N;!dbKB)k+3mNSt?%QU%@F%wNa-|9RsjuSv%A6Lv`}-x&zhf9p^6e4wrDwz zeDot9W;UPk@~gMl56Ke47EuYx)zc;KdGb+CPv%GS@B1V9s;5zm9bnpRI4-5iG-bwdWWO8P?Y87%tXLw!_<_1Pee6hS z;O^bKyngcrSu@uzU*WN9j~r`0(Ys?U$mq}J#98wbt#J>aBBYwRediwc&-aWe^YWKo z=cQL(BS|WO$Q3c1_`v#&0>W<{gn>6vm;Uq{SNjB8JXWXKh9sd2*bdp0Zku=@{U3dSc=laG zdmKv2AeAHzNpdmR@P@|rp}v0L`vFVDLYrvtVxyu?9JRCOhm>&MvpP9JoMU}{pK-fJ zy%1`o2dWc;t5b0~HI%h+J-8O`da;NrIBAiZM|?#BNEcYljFUR0jy^c9Tt4M&ea>ze ztQ$6t4AV$I%-l5PYkn3!%=Wu)z`Ns~f{;@}eLyAQy+4AVR4Y*|EIo|!!$BeTVkZ}< zW)8I*%-O~m=sM40J|{IqMX4F7%2*0}j8iU6lQrdQHk7p*t#L0lz;_sGJ&=0nVO*&e z0|B=Y*ccrr%ekG(S;zT)U_0!IA>zD{bFIU$zj?MDfBu~W2q{Y zsU||T-CtE(i0X|3rcKKf3SL5knqGIU$5f)8ROM`C<(rDhH#(pn5wA`Q~0HBH3`L<_rA12Osc<3m_Wpm`yJh5Th`lRZO+bhgn(0(Z`N^_wUzx zckkRdKfm{*@4SeA`xU4L|Er}^a%sd?t^uv;MWfp}N;O)S+KBu@usGach6nhdfv1ED zYAEXttRh=mT zp!tqkGrRN6Zo4`E^f*m#E711$vM%O?OQF;P$za?fVxU$jt)^}^{y?IK3k`c?Z)D^g zp;6deR5iU9Iv>g2GbyB8AZ4@^Y8V)uq3B%STSeA;s!UWILrrLa*a!0ldhuCWv$1+9 zc-K*?IrYO(h^j)VY}RY;-o5j=^}WsCyuD8EI->7T3_)+^B_~9^5v*cU?J7{~WXw|{ z4TKx5F~dj*#sL>&w0e$eW8%%I7G|>^DTOjd&Pw9m?K_lV&!yQCpEJ6eA*B#cR>Xys zDr!!oS|FQtPnIiuF%F>WjM>*_(Uhu%!ib6o=c!I@22Eku?YVd3PQCr*8$Wx#x%>0a zJoC5TRrVhsl$@!eh&E1t=P;%<F|ANE#RjBxO4KQnTqUWYoZ)~bwNX>!dC1f@ zivm0s=@c6ia#~rf7K|sSoKF+euxAt{mt^zBA(DNzGIJ{63N6E#2 zyPIvLlwKOvqh z(Gbixh%_E*MZ`v_#98f1bwr(Knljt-4cD)~{_5G;*(Y}U;g{Ci{XgUfe)#^|G1>Sa zSEy}>xs=Q_2_Yy_+irIkBcm}G09Ks!3vy{}S6Gc-4+Kj<9&M^-y*a0*$~<)RaYksp zhME&1fz|0{K)7@3HoMIh-$mqfh5A7Do^385)o$JsN01Jm5i&dpnA z*I&Q!H`crT|M2t=e&T`8^S)gxbaBRklc%(yh!6_38kx3uPw>_&c4C?6kvsY@eOQf{ zwd6{fCdO&cox68AzjvR!ADPFj`8$nGelWSs36YJf6I=_GRD|c?+{re^5pX5I8iaP&4?+Ts+XLBRBR^x8dM)@lg za7HcTYHnkm2GB}rg3>B;T5z?JwJ=VFR4S^5``qq#jBa4p&*=N!YBR$~8uy%S)`ss4 zo^G*35yq6!-JZ_bJ(CiGF~+5W^XBxYl**lZXV>rCz4zJuF#TvAHvizcv+mBvKkDwcQ_34gAm=A|jP(8W3@)$g!teiqQy^T97wzg%&C?^ek4VL?RO# z(r%!n#BQ@e6!K)D<&Xx3F(I|G+3lHKx`d`oo)SrR_!99kGIuj{98uM(s%adD^UeAC z6Jsj>>-ml8xu-w=i9PR2c1Z&fzh~ z?6i^_8HVp70{9A26e*69GHKX1j=F5uVud9VCPT8-!Z4*a2{k2aj+9axy6nK$tQ4)*HxOy}!8EoM zDmVjM9p-Us2>1wbZh70t4z0b#uE7)AFm+dzR14V&M2`e-alR^93oZvrnaVJXzaY;2 z_a*N?bN|k;p8na3_a3$Yf4?jAy-lyfMHMuL9-UtZJm+jv=9-B{A+IPS^gbR51GF-At;&yZOp%;vZ*LWEL^rm1YFara6t^_imj zBmejdH(!0`E9lnk;9DL3qBrd9dRaA+RBF4jP=x9|C1phFu~`nh!AzB7Z&(@ulS6T{ zfDeN20&eouZ2bLw>(>4&N%#Q4 zACV7@ufYqh7_1OywDJN(XFNPpHRo&eFc(U&+K^q=Y!fRsTwTCO^@0$5kL!#?&sDnz zpzjSaUA=E~HjbQc2 zI00}Gjvhw;50AZ786kw@eD0x3mRf(n)97Qw_~MT2>W3?WR1JSuD;^s=DAnO`OA+@W zsnZ;I+xdDP_Btw{*77DNdJy=z}$-c`&n}61ss;P>z&|$a=S1;zuCF~?;2?9pLbo{ o7x0!47&5TQp?pOqUT - - - - - All Blogs - - -

All Blogs

-
    - <% blogs.forEach(function(blog) { %> -
  • -

    <%= blog.title %>

    -

    <%= blog.text %>

    -

    <%= blog.place.name %>: View Place

    -

    Author: <%= blog.author.name %>

    -

    Likes: <%= blog.likes %>

    - View -
    - -
    -
  • - <% }) %> -
- New Blog - - From 3e3479514293d558e2de66bb8ae30fb91d3804d9 Mon Sep 17 00:00:00 2001 From: raseshr Date: Sat, 25 Mar 2023 11:06:02 -0400 Subject: [PATCH 62/93] delete any review by admin --- app.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 64aab5f81..9a15999bf 100644 --- a/app.js +++ b/app.js @@ -769,13 +769,34 @@ app.delete('/admin/places/:id', async (req, res) => { return res.status(404).send('Place not found'); } await Place.findByIdAndDelete(req.params.id); - res.redirect('/places'); + res.redirect('/admin/places'); } catch (err) { console.error(err); res.send('Error Deleting Place'); } }); +// delete any review +app.delete('/admin/places/:placeId/reviews/:reviewId', async (req, res) => { + try { + const review = await Review.findById(req.params.reviewId); + if (!review) { + return res.status(404).send('Review not found'); + } + await Review.findByIdAndDelete(req.params.reviewId); + const place = await Place.findById(req.params.placeId); + if (!place) { + return res.status(404).send('Place not found'); + } + place.reviews.pull(req.params.reviewId); + await place.save(); + res.redirect(`/admin/places/${req.params.placeId}`); + + } catch (error) { + console.log(error); + res.status(500).send('Server error'); + } +}); /* ---------- [End] Admin Modification Routes ---------- */ From 450ccb6cc82e90e0ba19c4879df4cc6d7878ec96 Mon Sep 17 00:00:00 2001 From: raseshr Date: Sat, 25 Mar 2023 11:10:20 -0400 Subject: [PATCH 63/93] delete blogs by admin initial --- app.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app.js b/app.js index 9a15999bf..0e0ded296 100644 --- a/app.js +++ b/app.js @@ -798,6 +798,17 @@ app.delete('/admin/places/:placeId/reviews/:reviewId', async (req, res) => { } }); +// DELETE specific blog by ID +app.delete('/admin/blogs/:id', async (req, res) => { + try { + await Blog.findByIdAndDelete(req.params.id); + res.redirect('/admin/blogs'); + } catch (err) { + console.log(err); + res.send('Error deleting blog'); + } +}); + /* ---------- [End] Admin Modification Routes ---------- */ From 07753d32c3b9ed117a0538840acccf0d07208ec9 Mon Sep 17 00:00:00 2001 From: Antony Date: Sat, 25 Mar 2023 13:12:09 -0400 Subject: [PATCH 64/93] Changing GET specific blog using ID to fit needs of frontend --- app.js | 11 ++++++++--- uploads/meowdy.png | Bin 12094 -> 13064 bytes uploads/ok.png | Bin 0 -> 5068 bytes 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 uploads/ok.png diff --git a/app.js b/app.js index 5ea1249b6..b8e1e4dac 100644 --- a/app.js +++ b/app.js @@ -750,8 +750,13 @@ app.post('/blogs', upload.array('blog-images'), async (req, res) => { // GET specific blog by ID app.get('/blogs/:id', async (req, res) => { try { - const blog = await Blog.findById(req.params.id).populate('author'); - res.render('blog', { blog }); + const blog = await Blog.findById(req.params.id); + const user = await User.findById(blog.author); + const response = { + ...blog.toObject(), + authorName: user.name + }; + res.send(response); } catch (err) { console.log(err); res.send('Error retrieving blog'); @@ -884,7 +889,7 @@ app.post('/blogs/:blogId/like/:userId', async (req, res) => { await blog.save(); // await user.save(); - return res.json({ blog }); + return res.send(blog); } catch (error) { console.log(error); res.status(500).send('Server error'); diff --git a/uploads/meowdy.png b/uploads/meowdy.png index 0a398c7f8ce56ddcd24a876fa90f80fb4c6d5bc4..99ed2d531fa7e94bbfe6546d40c9dedbde3bb28f 100644 GIT binary patch literal 13064 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 Ha`gWI3vsDD literal 12094 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

S!Qqmxv&5=Kex297Htv8 z+%Pmmyf z2~c9uC7MG2&&0GMO9?u)l1bH%CI)?r3#6W*-+b+FpBBXo>cmq?ek&{k16PmusHU_B zpy~U!@0a<9Sbum3ZUD4f_#th&Ru3BXNY9}_bf%2kN{5TO~{gs%ns zYZhbXIEf+g@YU-jCWI2lo- z)#`NWhyU^D+H#VFi*}L5o(X!8^Q&*DcJiGn1qB-ib~R>uhF>TQ zZrp-HBBkNnn8;&4r}5%Y@9+yDhxi$+Wce#PkMGm}wU?hWS_>fK9byvFhxkx3mB#7j zc`=eK4tD8vr1!3x>9CCUXr~JQvE}v!a${@c@&S_$atlul2_>uP!5>MgVgVyNxdO0AUEj2esYr=Z z8!r$ppy?VY>X?#TEXS_r&F+3Tx2Hlq#`jX_WL(ua zovK(o3edkhV{SIRuVw-kCk{^WUA3w?M>vG7qEk5g^+?v^u8P?Q7V=@j|P zwQ&s|&g!1R3s2$Wj&7>_YbI$O6pj@wQNewbA2*IH39%HVUQ>E<_XTL{_-q@D?oMN? zumlA70tIfGx_`*Za4uCiK_K=0ZAZGfs-Hd;?{wy{{7Oj}P%{%{8Y3K`Sq6vmDREu=R9 zNbpMB49FlXu#GBq_Tj19WM|}ND@mN^E9i#^2-?Gwqx=~@Rziv6kn7!9|EpqE2SNvG zHT+>5<~T{6 Date: Sat, 25 Mar 2023 19:22:06 -0400 Subject: [PATCH 65/93] Add unsave blog functionality --- app.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/app.js b/app.js index b8e1e4dac..37b241149 100644 --- a/app.js +++ b/app.js @@ -785,29 +785,33 @@ app.delete('/blogs/:id', async (req, res) => { // Save specific blog by ID app.post('/save-blog/:id', async (req, res) => { try { + if (!currentUser) { res.send("no user logged in"); return; } + if (currentUser.savedBlogs.includes(req.params.id)) { - res.send("blog already saved"); - return; + currentUser.savedBlogs.pop(req.params.id); + } else { + currentUser.savedBlogs.push(req.params.id); + User.findOneAndUpdate( + { _id: currentUser._id }, + { savedBlogs: currentUser.savedBlogs }, function (err) { + if (err) { + console.log(err); + res.sendStatus(500); + } else { + res.status(201).send("success") + } + }); } - currentUser.savedBlogs.push(req.params.id); - User.findOneAndUpdate( - { _id: currentUser._id }, - { savedBlogs: currentUser.savedBlogs }, function (err) { - if (err) { - console.log(err); - res.sendStatus(500); - } else { - res.status(201).send("success") - } - }); + } catch (err) { console.log(err); res.send('Error saving blogs'); } + }); // Get saved blogs of the current user From 42b7e8ad7000a44900d7def27d6e53cd087dae22 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 26 Mar 2023 08:56:30 -0400 Subject: [PATCH 66/93] Slightly modified endpoint for deleting a place --- app.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/app.js b/app.js index 37b241149..2ab92286f 100644 --- a/app.js +++ b/app.js @@ -462,16 +462,17 @@ app.get('/places/:id', async (req, res) => { // .catch((err) => console.log(err)); // }); -// // for removing a place -// app.delete('/:place_id', (req, res) => { -// Place.findByIdAndDelete(req.params.id, (err) => { -// if (err) { -// console.log(err); -// } else { -// res.render("landing"); -// } -// }); -// }); +app.delete('/places/:place_id', (req, res) => { + console.log("testing") + Place.findByIdAndDelete(req.params.place_id, (err) => { + if (err) { + console.log(err); + } else { + console.log("Place deleted"); + } + }); +}); + /* ---------- [End] Place Routes ---------- */ From 4dc39c3dc1b12fcf7e183c7978296a7b7291f5da Mon Sep 17 00:00:00 2001 From: Antony Date: Sun, 26 Mar 2023 13:14:28 -0400 Subject: [PATCH 67/93] Sending blog data upon creation --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 2ab92286f..14d2fa3be 100644 --- a/app.js +++ b/app.js @@ -741,7 +741,7 @@ app.post('/blogs', upload.array('blog-images'), async (req, res) => { const newBlog = new Blog({ title, text, author, tags, images }); const savedBlog = await newBlog.save(); - res.status(201).json(savedBlog); + res.status(201).send(savedBlog); } catch (err) { console.error(err); res.status(500).send('Server error'); From f2f74ca2f42947a6cfa6e29561842f48a3f34d98 Mon Sep 17 00:00:00 2001 From: Antony Date: Sun, 26 Mar 2023 18:22:01 -0400 Subject: [PATCH 68/93] Edited delete place endpoint so avoid conflicts with review deletion --- app.js | 2 +- uploads/meowdy.png | Bin 13064 -> 0 bytes uploads/ok.png | Bin 5068 -> 0 bytes 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 uploads/meowdy.png delete mode 100644 uploads/ok.png diff --git a/app.js b/app.js index 14d2fa3be..65e5ed6f4 100644 --- a/app.js +++ b/app.js @@ -462,7 +462,7 @@ app.get('/places/:id', async (req, res) => { // .catch((err) => console.log(err)); // }); -app.delete('/places/:place_id', (req, res) => { +app.delete('/places/delete/:place_id', (req, res) => { console.log("testing") Place.findByIdAndDelete(req.params.place_id, (err) => { if (err) { diff --git a/uploads/meowdy.png b/uploads/meowdy.png deleted file mode 100644 index 99ed2d531fa7e94bbfe6546d40c9dedbde3bb28f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13064 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 Ha`gWI3vsDD diff --git a/uploads/ok.png b/uploads/ok.png deleted file mode 100644 index 6d73b09d78c38f1f8a95f0f77d67cb8104010db0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5068 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

S!Qqmxv&5=Kex297Htv8 z+%Pmmyf z2~c9uC7MG2&&0GMO9?u)l1bH%CI)?r3#6W*-+b+FpBBXo>cmq?ek&{k16PmusHU_B zpy~U!@0a<9Sbum3ZUD4f_#th&Ru3BXNY9}_bf%2kN{5TO~{gs%ns zYZhbXIEf+g@YU-jCWI2lo- z)#`NWhyU^D+H#VFi*}L5o(X!8^Q&*DcJiGn1qB-ib~R>uhF>TQ zZrp-HBBkNnn8;&4r}5%Y@9+yDhxi$+Wce#PkMGm}wU?hWS_>fK9byvFhxkx3mB#7j zc`=eK4tD8vr1!3x>9CCUXr~JQvE}v!a${@c@&S_$atlul2_>uP!5>MgVgVyNxdO0AUEj2esYr=Z z8!r$ppy?VY>X?#TEXS_r&F+3Tx2Hlq#`jX_WL(ua zovK(o3edkhV{SIRuVw-kCk{^WUA3w?M>vG7qEk5g^+?v^u8P?Q7V=@j|P zwQ&s|&g!1R3s2$Wj&7>_YbI$O6pj@wQNewbA2*IH39%HVUQ>E<_XTL{_-q@D?oMN? zumlA70tIfGx_`*Za4uCiK_K=0ZAZGfs-Hd;?{wy{{7Oj}P%{%{8Y3K`Sq6vmDREu=R9 zNbpMB49FlXu#GBq_Tj19WM|}ND@mN^E9i#^2-?Gwqx=~@Rziv6kn7!9|EpqE2SNvG zHT+>5<~T{6 Date: Sun, 26 Mar 2023 18:34:06 -0400 Subject: [PATCH 69/93] Minor comment change + Remove place from view --- app.js | 2 +- views/new-blog.ejs | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app.js b/app.js index 14d2fa3be..0d7d5368b 100644 --- a/app.js +++ b/app.js @@ -783,7 +783,7 @@ app.delete('/blogs/:id', async (req, res) => { } }); -// Save specific blog by ID +// Save/Unsave specific blog by ID app.post('/save-blog/:id', async (req, res) => { try { diff --git a/views/new-blog.ejs b/views/new-blog.ejs index e58c3aff7..4412f0bff 100644 --- a/views/new-blog.ejs +++ b/views/new-blog.ejs @@ -16,14 +16,6 @@ -

- - -
-
- - -
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + + + diff --git a/backend/views/all_places.ejs b/backend/views/all_places.ejs new file mode 100644 index 000000000..8a51b22ce --- /dev/null +++ b/backend/views/all_places.ejs @@ -0,0 +1,26 @@ + + + + + All Places + + +

All Places

+
    + <% places.forEach(function(place) { %> +
  • +

    <%= place.name %>

    +

    <%= place.description %>

    +

    Average Rating: <%= place.avgRating %>

    +

    Number of Reviews: <%= place.numReviews %>

    +

    Type: <%= place.placeType %>

    + <% if (place.tags.length > 0) { %> +

    Tags: <%= place.tags.join(', ') %>

    + <% } %> +

    Location: <%= place.name %> on Google Maps

    +

    View

    +
  • + <% }); %> +
+ + diff --git a/backend/views/blog.ejs b/backend/views/blog.ejs new file mode 100644 index 000000000..a4578d870 --- /dev/null +++ b/backend/views/blog.ejs @@ -0,0 +1,21 @@ + + + + + + <%= blog.title %> + + +

<%= blog.title %>

+

<%= blog.text %>

+

Author: <%= blog.author.name %>

+

Likes: <%= blog.likes %>

+
+ +
+
+ +
+ All Blogs + + diff --git a/backend/views/blogs.ejs b/backend/views/blogs.ejs new file mode 100644 index 000000000..9c01ab796 --- /dev/null +++ b/backend/views/blogs.ejs @@ -0,0 +1,26 @@ + + + + + + All Blogs + + +

All Blogs

+
    + <% blogs.forEach(function(blog) { %> +
  • +

    <%= blog.title %>

    +

    <%= blog.text %>

    +

    Author: <%= blog.author.name %>

    +

    Likes: <%= blog.likes %>

    + View +
    + +
    +
  • + <% }) %> +
+ New Blog + + \ No newline at end of file diff --git a/backend/views/edit-review.ejs b/backend/views/edit-review.ejs new file mode 100644 index 000000000..2fc5371bb --- /dev/null +++ b/backend/views/edit-review.ejs @@ -0,0 +1,30 @@ + + + + + Edit Review + + +

Edit Review

+
+
+ + +
+
+ + +
+ +
+
+ +
+ + diff --git a/backend/views/edit_place.ejs b/backend/views/edit_place.ejs new file mode 100644 index 000000000..f3922591f --- /dev/null +++ b/backend/views/edit_place.ejs @@ -0,0 +1,67 @@ + + + + + + Edit Place + + +

Edit Place

+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+ + diff --git a/backend/views/forgotPassword.ejs b/backend/views/forgotPassword.ejs new file mode 100644 index 000000000..e15d94ea9 --- /dev/null +++ b/backend/views/forgotPassword.ejs @@ -0,0 +1,26 @@ +<%- include('partials/header') %> + +
+

Forgot Password? Let's Reset!

+ +
+
+
+
+ + +
+
+ + +
+ +
+
+
+
+ +
+
+ +<%- include('partials/footer') %> diff --git a/backend/views/home.ejs b/backend/views/home.ejs new file mode 100644 index 000000000..76c43e110 --- /dev/null +++ b/backend/views/home.ejs @@ -0,0 +1,17 @@ +<%- include('partials/header') %> + + +
+
+ +

AllPurdue

+

One stop platform for everything @ Purdue

+
+ Register + Login + Places + +
+
+ +<%- include('partials/footer') %> diff --git a/backend/views/landing.ejs b/backend/views/landing.ejs new file mode 100644 index 000000000..d1801ac18 --- /dev/null +++ b/backend/views/landing.ejs @@ -0,0 +1,14 @@ +<%- include('partials/header') %> + +
+
+ +

Welcome to AllPurdue! Here are the categories!!!

+
+ + Log Out + Submit a Secret +
+
+ +<%- include('partials/footer') %> diff --git a/backend/views/login.ejs b/backend/views/login.ejs new file mode 100644 index 000000000..24ebbb56a --- /dev/null +++ b/backend/views/login.ejs @@ -0,0 +1,47 @@ +<%- include('partials/header') %> + +
+

Login

+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +<%- include('partials/footer') %> diff --git a/backend/views/new-blog.ejs b/backend/views/new-blog.ejs new file mode 100644 index 000000000..4412f0bff --- /dev/null +++ b/backend/views/new-blog.ejs @@ -0,0 +1,34 @@ + + + + + + New Blog + + +

New Blog

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + diff --git a/backend/views/partials/footer.ejs b/backend/views/partials/footer.ejs new file mode 100644 index 000000000..d549cb0f8 --- /dev/null +++ b/backend/views/partials/footer.ejs @@ -0,0 +1,4 @@ + + + + diff --git a/backend/views/partials/header.ejs b/backend/views/partials/header.ejs new file mode 100644 index 000000000..d8be374ea --- /dev/null +++ b/backend/views/partials/header.ejs @@ -0,0 +1,13 @@ + + + + + + AllPurdue + + + + + + + diff --git a/backend/views/place-details.ejs b/backend/views/place-details.ejs new file mode 100644 index 000000000..9a6ec7d72 --- /dev/null +++ b/backend/views/place-details.ejs @@ -0,0 +1,49 @@ +

<%= place.name %>

+ +
+

<%= place.description %>

+

<%= place.placeType %>

+

<%= place.tags.join(', ') %>

+

Average Rating: <%= averageRating %>

+

Number of Reviews: <%= numRatings %>

+
+ +

Location:

+

<%= place.name %> on Google Maps

+ +

Reviews:

+ +<% if (place.reviews.length === 0) { %> +

No reviews yet. Be the first to leave a review!

+<% } else { %> + <% place.reviews.forEach(function(review) { %> +
+

Rating: <%= review.rating %>

+

<%= review.text %>

+
+ +
+ Edit Review +
+ <% }); %> +<% } %> + +

Add a Review:

+ +
+
+ + +
+
+ + +
+ +
\ No newline at end of file diff --git a/backend/views/register.ejs b/backend/views/register.ejs new file mode 100644 index 000000000..c01c984fc --- /dev/null +++ b/backend/views/register.ejs @@ -0,0 +1,45 @@ +<%- include('partials/header') %> +
+

Register

+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+
+ + + +
+
+ +<%- include('partials/header') %> diff --git a/backend/views/reset-password.ejs b/backend/views/reset-password.ejs new file mode 100644 index 000000000..3a92966a1 --- /dev/null +++ b/backend/views/reset-password.ejs @@ -0,0 +1,29 @@ +<%- include('partials/header') %> + +
+

Reset your Password!

+ +
+
+
+
+ + +
+
+ +
+
+ + +
+ +
+
+
+
+ +
+
+ +<%- include('partials/footer') %> diff --git a/backend/views/reviews.ejs b/backend/views/reviews.ejs new file mode 100644 index 000000000..43fd55639 --- /dev/null +++ b/backend/views/reviews.ejs @@ -0,0 +1,12 @@ +

Reviews for <%= place.name %>:

+ +<% if (reviews.length === 0) { %> +

No reviews yet. Be the first to leave a review!

+<% } else { %> + <% reviews.forEach(function(review) { %> +
+

Rating: <%= review.rating %>

+

<%= review.text %>

+
+ <% }); %> +<% } %> diff --git a/backend/views/search.ejs b/backend/views/search.ejs new file mode 100644 index 000000000..f4a4ebfa9 --- /dev/null +++ b/backend/views/search.ejs @@ -0,0 +1,63 @@ + + + + + Search + + + + + +
+

All Purdue

+ +
+
+

Search

+
+ + + + +
+
+
+ + + \ No newline at end of file From 67381e3de920563fb982a16d17cc64bdaaec9f7a Mon Sep 17 00:00:00 2001 From: Antony Date: Sat, 15 Apr 2023 13:25:33 -0400 Subject: [PATCH 92/93] Moving node_modules to backend folder --- backend/package-lock.json | 1009 +------------------------------------ 1 file changed, 2 insertions(+), 1007 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 1d87a6406..0dc845a3c 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1321,74 +1321,16 @@ "node": ">=10" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/array.prototype.filter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.2.tgz", - "integrity": "sha512-us+UrmGOilqttSOgoWZTpOvHu68vZT2YCjc/H4vhu56vzZpaDFBhB+Se2UwqWzMKbDv7Myq5M5pcZLAtUvTQdQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/axios": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", @@ -1494,11 +1436,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -1642,42 +1579,6 @@ "node": "*" } }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1736,11 +1637,6 @@ "color-support": "bin.js" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1849,32 +1745,6 @@ "node": "*" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -1891,21 +1761,6 @@ "node": ">=0.10.0" } }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -1936,62 +1791,6 @@ "node": ">=8" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -2102,150 +1901,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/enzyme": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", - "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", - "dependencies": { - "array.prototype.flat": "^1.2.3", - "cheerio": "^1.0.0-rc.3", - "enzyme-shallow-equal": "^1.0.1", - "function.prototype.name": "^1.1.2", - "has": "^1.0.3", - "html-element-map": "^1.2.0", - "is-boolean-object": "^1.0.1", - "is-callable": "^1.1.5", - "is-number-object": "^1.0.4", - "is-regex": "^1.0.5", - "is-string": "^1.0.5", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.7.0", - "object-is": "^1.0.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1", - "object.values": "^1.1.1", - "raf": "^3.4.1", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.2.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/enzyme-shallow-equal": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.5.tgz", - "integrity": "sha512-i6cwm7hN630JXenxxJFBKzgLC3hMTafFQXflvzHgPmDhOBhxUWDe8AeRv1qp2/uWJ2Y8z5yLWMzmAfkTOiOCZg==", - "dependencies": { - "has": "^1.0.3", - "object-is": "^1.1.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2455,14 +2110,6 @@ } } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2529,31 +2176,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -2591,21 +2213,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2636,31 +2243,6 @@ "node": ">= 6" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2672,14 +2254,6 @@ "node": ">= 0.4.0" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2688,28 +2262,6 @@ "node": ">=4" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -2721,55 +2273,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, - "node_modules/html-element-map": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", - "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", - "dependencies": { - "array.prototype.filter": "^1.0.0", - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2867,19 +2375,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", @@ -2889,32 +2384,8 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.10" } }, "node_modules/is-binary-path": { @@ -2928,51 +2399,11 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3000,17 +2431,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -3019,108 +2439,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==" - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3223,21 +2541,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -3514,11 +2817,6 @@ "resolved": "https://registry.npmjs.org/mongoose-findorcreate/-/mongoose-findorcreate-3.0.0.tgz", "integrity": "sha512-kQhDe5XDj6tMv8kq1wjK+hITGIGUl60rj8oGLupF9poNsqIDkAJBXudZKcCdSyBZ7p6DLK2+0jSBthrb26tSYQ==" }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" - }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -3592,27 +2890,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -3732,17 +3009,6 @@ "set-blocking": "^2.0.0" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/oauth": { "version": "0.9.15", "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", @@ -3764,75 +3030,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -3860,29 +3057,6 @@ "wrappy": "1" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3988,11 +3162,6 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -4048,31 +3217,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -4127,30 +3271,6 @@ "node": ">=8.10.0" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -4165,15 +3285,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==", - "dependencies": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4193,19 +3304,6 @@ } ] }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -4484,48 +3582,6 @@ "node": ">=8" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4629,19 +3685,6 @@ "node": ">= 0.6" } }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -4663,20 +3706,6 @@ "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -4745,40 +3774,6 @@ "node": ">=12" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", From 5926d7690a3659c708940db7a36ea6bc5e57566c Mon Sep 17 00:00:00 2001 From: Antony Date: Sat, 15 Apr 2023 13:35:13 -0400 Subject: [PATCH 93/93] Merge conflict fix? --- backend/.env | 5 +++++ backend/.gitignore | 27 +++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 backend/.env diff --git a/backend/.env b/backend/.env new file mode 100644 index 000000000..e9e1c5084 --- /dev/null +++ b/backend/.env @@ -0,0 +1,5 @@ +SESSION_SECRET=secretuwgfugeurvrtrr +JWT_SECRET=yaudbwedubfuebufbashbayash +APP_PASS=tmwwstrgjmofdiuz +CLIENT_ID=1022274060459-lq1e7425n3qua3ujvgaqbfm44rn4hba4.apps.googleusercontent.com +CLIENT_SECRET=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 \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore index 3ec544c7a..6229a60e0 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,2 +1,25 @@ -node_modules/ -.env \ No newline at end of file +# dependencies +/node_modules +/.pnp +.pnp.js + +# package lock +!**/package-lock.json + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log*