diff --git a/package-lock.json b/package-lock.json index a0eb075..6832058 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "jsonwebtoken": "^8.5.1", "mongoose": "^6.1.2", "morgan": "^1.10.0", + "multer": "^1.4.4", "validator": "^13.7.0" }, "devDependencies": { @@ -243,6 +244,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": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -448,6 +454,39 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "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": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/busboy/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/busboy/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "node_modules/bytes": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", @@ -634,6 +673,52 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "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/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -688,6 +773,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "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", @@ -809,6 +899,34 @@ "node": ">=0.10" } }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dicer/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/dicer/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1710,6 +1828,11 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1996,8 +2119,7 @@ "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "node_modules/minipass": { "version": "3.1.6", @@ -2143,6 +2265,35 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2460,6 +2611,11 @@ "node": ">=4" } }, + "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/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -2867,6 +3023,14 @@ "node": ">= 0.6" } }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3048,6 +3212,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -3274,6 +3443,14 @@ "node": ">=8" } }, + "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", @@ -3451,6 +3628,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -3604,6 +3786,38 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "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==" + }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "bytes": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", @@ -3741,6 +3955,51 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "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" + } + }, + "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==" + }, + "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==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -3783,6 +4042,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "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==" + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -3869,6 +4133,33 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4552,6 +4843,11 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4787,8 +5083,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minipass": { "version": "3.1.6", @@ -4900,6 +5195,31 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5140,6 +5460,11 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "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==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5454,6 +5779,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5586,6 +5916,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -5761,6 +6096,11 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "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 c07558c..738acd7 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "jsonwebtoken": "^8.5.1", "mongoose": "^6.1.2", "morgan": "^1.10.0", + "multer": "^1.4.4", "validator": "^13.7.0" }, "devDependencies": { diff --git a/src/config/auth.js b/src/config/auth.js deleted file mode 100644 index ec146ed..0000000 --- a/src/config/auth.js +++ /dev/null @@ -1,53 +0,0 @@ -const jwt = require("jsonwebtoken"); -const { JWT_SECRET } = require("./env"); -const User = require("../models/User"); -const constants = require("./constants"); - -const authenticate = async (token) => { - const decodedToken = jwt.verify(token, JWT_SECRET); - if (decodedToken) { - return await User.findById(decodedToken.id) - .populate({ path: "roles", populate: "permissions" }) - .populate("permissions"); - } -}; - -const authorize = async ( - user, - requiredRoles = [], - requiredPermissions = [] -) => { - const userRoles = user.roles.map((_) => _._id); - const userPermissions = [ - ...user.permissions.map((_) => _._id), - ...userRoles.map((_) => _.permissions).flat(), - ]; - - return ( - user != undefined && - requiredRoles.every((_) => userRoles.includes(_)) && - requiredPermissions.every((_) => userPermissions.includes(_)) - ); -}; - -module.exports = { - AuthenticateMiddleware: async (req, res, next) => { - try { - const token = req.headers.authorization || ""; - if (token) { - const user = authenticate(token); - res.locals.user = user; - next(); - } - } catch (error) { - res - .status(401) - .send({ - success: false, - error: constants.AUTHENTICATION_FAILURE_ERROR_MESSAGE, - }); - } - }, - - AuthorizeUser: authorize, -}; diff --git a/src/controller/dashboard.controller.js b/src/controller/dashboard.controller.js new file mode 100644 index 0000000..288f5b2 --- /dev/null +++ b/src/controller/dashboard.controller.js @@ -0,0 +1,328 @@ +const mongoose = require("mongoose"); + +const Warehouse = require("../models/Warehouse"); +const Zone = require("../models/Zone"); +const Area = require("../models/Area"); +const Row = require("../models/Row"); +const Bay = require("../models/Bay"); +const Level = require("../models/Level"); +const Sublevel = require("../models/Sublevel"); +const Inventory = require("../models/Inventory"); +const Material = require("../models/Material"); +const Item = require("../models/Item"); + +const createWarehouse = async ({ name, address, specs, company_id }) => { + if (!(name && address)) { + return; + } + + return await Warehouse.create({ + name, + address, + specs, + company_id: mongoose.Types.ObjectId(company_id), + }); +}; + +const createZones = async (zones, warehouse) => { + const zonesArr = []; + for (const zone of zones) { + const { name, type, specs } = zone; + + const zoneObj = new Zone({ + name, + type, + specs, + warehouse_id: mongoose.Types.ObjectId(warehouse._id), + }); + + await zoneObj.save(); + + if (zone.areas) { + zoneObj.areas = await createAreas(zone.areas, zoneObj); + } + + zonesArr.push(zoneObj); + } + return zonesArr; +}; + +const createAreas = async (areas, zone) => { + const areasArr = []; + for (const area of areas) { + const { name, type, specs } = area; + const areaObj = new Area({ + name, + type, + specs, + zone_id: mongoose.Types.ObjectId(zone._id), + }); + + await areaObj.save(); + if (area.rows) { + areaObj.rows = await createRows(zone.areas, area); + } + areasArr.push(areaObj); + } + return areasArr; +}; + +const createRows = async (rows, area) => { + const rowsArr = []; + for (const row of rows) { + const { name, number, specs } = row; + const rowObj = new Row({ + name, + number: parseInt(number), + specs, + area_id: mongoose.Types.ObjectId(area._id), + }); + + await rowObj.save(); + if (row.bays) { + rowObj.bays = await createBays(row.bays, row); + } + rowsArr.push(rowObj); + } + return rowsArr; +}; + +const createBays = async (bays, row) => { + const baysArr = []; + for (const bay of bays) { + const { name, number, type, specs } = bay; + const bayObj = new Bay({ + name, + number: parseInt(number), + type, + specs, + row_id: mongoose.Types.ObjectId(row._id), + }); + + await bayObj.save(); + if (bay.levels) { + bayObj.levels = await createLevels(bay.levels, bay); + } + baysArr.push(bayObj); + } + return baysArr; +}; + +const createLevels = async (levels, bay) => { + const levelsArr = []; + for (const level of levels) { + const { name, number, specs } = level; + const levelObj = new Level({ + name, + number: parseInt(number), + specs, + row_id: mongoose.Types.ObjectId(bay._id), + }); + + await levelObj.save(); + if (level.levels) { + levelObj.subLevels = await createSublevels(level.subLevels, level); + } + levelsArr.push(levelObj); + } + return levelsArr; +}; + +const createSublevels = async ( + subLevels, + level, + parent = undefined, + depth = 0 +) => { + const subLevelsArr = []; + for (const subLevel of subLevels) { + const subLevelObj = await Sublevel.create({ + name: subLevel.name, + type: subLevel.type, + specs: subLevel.specs, + main_level_id: level._id, + current_depth: depth, + parent_subLevel_id: parent ? parent._id : undefined, + has_inventory: subLevel.has_inventory, + inventory: subLevel.inventory, + }); + + if (subLevel.sub_levels) { + const subSubLevels = await createSublevels( + subLevel.sub_levels, + level, + subLevelObj, + depth + 1 + ); + + subLevelObj.sub_levels = subSubLevels.map((_) => { + return { + type: _.type, + depth: _.depth, + sub_level_id: _._id, + }; + }); + + await subLevelObj.save(); + } + + subLevelsArr.push(subLevelObj); + } + return subLevelsArr; +}; + +const createInventory = async ({ name, type }) => { + if (!(name && type)) { + return; + } + + return await Inventory.create({ + name, + type, + }); +}; + +const createItems = async (items, material) => { + const itemsArray = []; + for (const itemData of items) { + const item = { + commonName: itemData.commonName, + formalName: itemData.formalName, + description: itemData.description, + manufacturer: itemData.manufacturer, + size: itemData.size, + color: itemData.color, + type: itemData.type, + unitOfMaterial: itemData.unitOfMaterial, + unitCost: itemData.unitCost, + packageCount: itemData.packageCount, + countPerPallet: itemData.countPerPallet, + countPerPalletPackage: itemData.countPerPalletPackage, + customAttributes: itemData.customAttributes, + material, + }; + + if (Object.values(item).every((_) => _)) { + const itemObj = await Item.create(item); + itemsArray.push(itemObj); + } + } + return itemsArray; +}; + +const createMaterials = async (materials, inventory, parent = undefined) => { + const materialsData = []; + for (const materialData of materials) { + const material = await Material.create({ + name, + parent, + inventory, + }); + + let materialFamily; + if (materialData.family) { + materialFamily = await createMaterials( + materialData.family, + inventory, + material + ); + } + + let items; + if (materialData.items) { + items = await createItems(materialData.items, material); + } + + materialsData.push({ + material, + family: materialFamily, + items, + }); + } + + return materialsData; +}; + +module.exports = { + createWarehouseSchema: async (req, res, next) => { + try { + const warehouseSchema = {}; + if (!req.body.warehouse) { + res.status(400).send({ + success: false, + message: "Creation of Warehouse Failed, missing params", + }); + return; + } + + const warehouse = await createWarehouse(req.body.warehouse); + if (!warehouse) { + res.status(400).send({ + success: false, + message: "Creation of Warehouse Failed, invalid/missing params", + }); + return; + } + + warehouseSchema.warehouse = warehouse; + if (!req.body.warehouse.zones) { + const zones = createZones(req.body.warehouse.zones, warehouse); + if (!zones) { + res.status(400).send({ + success: false, + message: "Creation of Zones Failed, invalid/missing params", + }); + return; + } + + warehouseSchema.warehouse.zones = zones; + } + res.send({ success: true, data: warehouseSchema }); + } catch (error) { + next(error); + } + }, + createInventorySchema: async (req, res, next) => { + try { + const inventorySchema = {}; + if (!req.body.inventory) { + res.status(400).send({ + success: false, + message: "Creation of Inventory Failed, missing params", + }); + return; + } + + const inventory = await createInventory(req.body.inventory); + + if (!inventory) { + res.status(400).send({ + success: false, + message: "Creation of Inventory Failed, invalid/missing params", + }); + return; + } + inventorySchema.inventory = inventory; + + if (req.body.inventory.materials) { + const materials = createMaterials( + req.body.inventory.materials, + inventory + ); + if (!materials) { + res.status(400).send({ + success: false, + message: "Creation of Materials Failed, invalid/missing params", + }); + return; + } + + inventorySchema.inventory.materials = materials; + } + + res.send({ success: true, data: inventorySchema }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/dashboard.router.js b/src/controller/dashboard.router.js new file mode 100644 index 0000000..2781589 --- /dev/null +++ b/src/controller/dashboard.router.js @@ -0,0 +1,14 @@ +const router = require("express").Router(); +const controller = require("./dashboard.controller"); + +/** + * @route /dashboard/create-warehouse-schema + */ +router.post("/create-warehouse-schema", controller.createWarehouseSchema); + +/** + * @route /dashboard/create-inventory-schema + */ +router.post("/create-inventory-schema", controller.createInventorySchema); + +module.exports = router; diff --git a/src/controller/index.js b/src/controller/index.js index d1b41a7..32b0360 100644 --- a/src/controller/index.js +++ b/src/controller/index.js @@ -2,7 +2,7 @@ const router = require("express").Router(); const userRouter = require("./user.router"); const userRoleRouter = require("./userRole.router"); const userPermissionRouter = require("./userPermission.router"); -const { AuthenticateMiddleware } = require("../config/auth"); +const { AuthenticateMiddleware } = require("./utils/authorize"); const companyRouter = require("./company.router"); const warehouseRouter = require("./warehouse.router"); @@ -12,6 +12,7 @@ const bayRouter = require("./bay.router"); const rowRouter = require("./row.router"); const levelRouter = require("./level.router"); const sublevelRouter = require("./sublevel.router"); +const dashboardRouter = require("./dashboard.router"); router.use("/user-role", AuthenticateMiddleware, userRoleRouter); router.use("/user-permission", AuthenticateMiddleware, userPermissionRouter); @@ -25,6 +26,7 @@ router.use("/row", rowRouter); router.use("/level", levelRouter); router.use("/sublevel", sublevelRouter); +router.use("/dashboard", dashboardRouter); router.get("/", (req, res) => { res.send({ success: true, message: "Hello world" }); diff --git a/src/controller/inventory.controller.js b/src/controller/inventory.controller.js new file mode 100644 index 0000000..9175e00 --- /dev/null +++ b/src/controller/inventory.controller.js @@ -0,0 +1,89 @@ +const Inventory = require("../models/Inventory"); + +module.exports = { + /** + * Gets the Inventory data by `id` + */ + getInventoryByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + try { + const inventoryData = await Inventory.findById(id); + if (!inventoryData) { + res.status(404); + return; + } + req.send({ success: true, data: inventoryData }); + } catch (error) { + next(error); + } + }, + + /** + * Create a Inventory + */ + createInventory: async (req, res, next) => { + const { name, type } = req.body; + + if (!(name && type)) { + res.status(400).send("Missing params param"); + return; + } + + try { + const inventoryData = new Inventory({ + name, + type, + }); + + await inventoryData.save(); + if (!inventoryData) { + res.status(404); + return; + } + req.send({ success: true, data: inventoryData }); + } catch (error) { + next(error); + } + }, + + /** + * Update a Inventory detail + */ + updateInventoryByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + const { name, type } = req.body; + + if (!(name || type)) { + res.status(400).send("Missing data in body"); + return; + } + + try { + const inventoryData = await Inventory.findById(id); + if (!inventoryData) { + res.status(404); + return; + } + + if (name) inventoryData.name = name; + if (type) inventoryData.type = type; + + await inventoryData.save(); + req.send({ success: true, data: inventoryData }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/inventory.router.js b/src/controller/inventory.router.js new file mode 100644 index 0000000..a00ad8e --- /dev/null +++ b/src/controller/inventory.router.js @@ -0,0 +1,19 @@ +const router = require("express").Router(); +const controller = require("./inventory.controller"); + +/** + * @route /inventory/:id + */ +router.get("/:id", controller.getInventoryByID); + +/** + * @route /inventory/ + */ +router.post("/", controller.createInventory); + +/** + * @route /inventory/ + */ +router.patch("/:id", controller.updateInventoryByID); + +module.exports = router; diff --git a/src/controller/item.controller.js b/src/controller/item.controller.js new file mode 100644 index 0000000..1653df2 --- /dev/null +++ b/src/controller/item.controller.js @@ -0,0 +1,119 @@ +const mongoose = require("mongoose"); +const Item = require("../models/Item"); +const Material = require("../models/Material"); + +module.exports = { + /** + * Gets the Item data by `id` + */ + getItemByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + try { + const itemData = await Item.findById(id); + if (!itemData) { + res.status(404); + return; + } + req.send({ success: true, data: itemData }); + } catch (error) { + next(error); + } + }, + + /** + * Create a Item + */ + createItem: async (req, res, next) => { + let material; + if (req.body.materialId && mongoose.isValidObjectId(req.body.materialId)) { + material = await Material.findById(material); + } + const item = { + commonName: req.body.commonName, + formalName: req.body.formalName, + description: req.body.description, + manufacturer: req.body.manufacturer, + size: req.body.size, + color: req.body.color, + type: req.body.type, + unitOfMaterial: req.body.unitOfMaterial, + unitCost: req.body.unitCost, + packageCount: req.body.packageCount, + countPerPallet: req.body.countPerPallet, + countPerPalletPackage: req.body.countPerPalletPackage, + customAttributes: req.body.customAttributes, + material, + }; + + if (Object.values(item).every((_) => _)) { + res.status(400).send("Missing params param"); + return; + } + + try { + const itemData = new Item(item); + + await itemData.save(); + if (!itemData) { + res.status(404); + return; + } + req.send({ success: true, data: itemData }); + } catch (error) { + next(error); + } + }, + + /** + * Update a Item detail + */ + updateItemByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + const item = { + commonName: req.body.commonName, + formalName: req.body.formalName, + description: req.body.description, + manufacturer: req.body.manufacturer, + size: req.body.size, + color: req.body.color, + type: req.body.type, + unitOfMaterial: req.body.unitOfMaterial, + unitCost: req.body.unitCost, + packageCount: req.body.packageCount, + countPerPallet: req.body.countPerPallet, + countPerPalletPackage: req.body.countPerPalletPackage, + customAttributes: req.body.customAttributes, + }; + + try { + const itemData = await Item.findById(id); + if (!itemData) { + res.status(404); + return; + } + + for (const key of Object.keys(item)) { + if (item[key] !== undefined) { + itemData[key] = item[key]; + } + } + + await itemData.save(); + req.send({ success: true, data: itemData }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/item.router.js b/src/controller/item.router.js new file mode 100644 index 0000000..effbc24 --- /dev/null +++ b/src/controller/item.router.js @@ -0,0 +1,19 @@ +const router = require("express").Router(); +const controller = require("./item.controller"); + +/** + * @route /item/:id + */ +router.get("/:id", controller.getItemByID); + +/** + * @route /item/ + */ +router.post("/", controller.createItem); + +/** + * @route /item/ + */ +router.patch("/:id", controller.updateItemByID); + +module.exports = router; diff --git a/src/controller/material.controller.js b/src/controller/material.controller.js new file mode 100644 index 0000000..da5fb4e --- /dev/null +++ b/src/controller/material.controller.js @@ -0,0 +1,122 @@ +const mongoose = require("mongoose"); +const Material = require("../models/Material"); +const Inventory = require("../models/Inventory"); + +module.exports = { + /** + * Gets the Material data by `id` + */ + getMaterialByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + try { + const materialData = await Material.findById(id); + if (!materialData) { + res.status(404); + return; + } + req.send({ success: true, data: materialData }); + } catch (error) { + next(error); + } + }, + + /** + * Create a Material + */ + createMaterial: async (req, res, next) => { + const { name, parentId, inventoryId } = req.body; + + try { + let parent; + if (parentId && mongoose.isValidObjectId(parentId)) { + parent = await Material.findById(parent); + } else if (parentId && !mongoose.isValidObjectId(parentId)) { + res.status(400).send("Invalid params parentId"); + return; + } + + let inventory; + if (inventoryId && mongoose.isValidObjectId(inventoryId)) { + inventory = await Inventory.findById(inventoryId); + } else { + res.status(400).send("Invalid params inventoryId"); + return; + } + + const materialData = new Material({ + name, + parent, + inventory, + }); + + await materialData.save(); + if (!materialData) { + res.status(404); + return; + } + req.send({ success: true, data: materialData }); + } catch (error) { + next(error); + } + }, + + /** + * Update a Material detail + */ + updateMaterialByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + const { name, parentId, inventoryId } = req.body; + + if (!(name || parentId || inventoryId)) { + res.status(400).send("Missing data in body"); + return; + } + + try { + const materialData = await Material.findById(id); + if (!materialData) { + res.status(404); + return; + } + + if (name) { + materialData.name = name; + } + + let parent; + if (parentId && mongoose.isValidObjectId(parentId)) { + parent = await Material.findById(parent); + materialData.parent = parent; + } else if (parentId && !mongoose.isValidObjectId(parentId)) { + res.status(400).send("Invalid params parentId"); + return; + } + + let inventory; + if (inventoryId && mongoose.isValidObjectId(inventoryId)) { + inventory = await Inventory.findById(inventoryId); + materialData.inventory = inventory; + } else { + res.status(400).send("Invalid params inventoryId"); + return; + } + + await materialData.save(); + req.send({ success: true, data: materialData }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/material.router.js b/src/controller/material.router.js new file mode 100644 index 0000000..7fa0873 --- /dev/null +++ b/src/controller/material.router.js @@ -0,0 +1,19 @@ +const router = require("express").Router(); +const controller = require("./material.controller"); + +/** + * @route /material/:id + */ +router.get("/:id", controller.getMaterialByID); + +/** + * @route /material/ + */ +router.post("/", controller.createMaterial); + +/** + * @route /material/ + */ +router.patch("/:id", controller.updateMaterialByID); + +module.exports = router; diff --git a/src/controller/sublevel.controller.js b/src/controller/sublevel.controller.js index 94c9eac..c028a81 100644 --- a/src/controller/sublevel.controller.js +++ b/src/controller/sublevel.controller.js @@ -1,4 +1,4 @@ -const SubLevel = require("../models/Sublevel"); +const Sublevel = require("../models/Sublevel"); const mongoose = require("mongoose"); module.exports = { @@ -14,7 +14,7 @@ module.exports = { } try { - const subLevelData = await SubLevel.findById(id); + const subLevelData = await Sublevel.findById(id); if (!subLevelData) { res.status(404); return; @@ -38,10 +38,10 @@ module.exports = { try { const { parent_current_depth, parent_main_level_id } = parent_sublevel_id - ? await SubLevel.findById(parent_sublevel_id) + ? await Sublevel.findById(parent_sublevel_id) : { current_depth: 1, p_main_level_id: main_level_id }; - const sublevelData = new SubLevel({ + const sublevelData = new Sublevel({ name, type: type, specs, @@ -74,7 +74,7 @@ module.exports = { } try { - const sublevelData = await SubLevel.findById(id); + const sublevelData = await Sublevel.findById(id); if (!sublevelData) { res.status(404); return; diff --git a/src/controller/user.router.js b/src/controller/user.router.js index 7c0c39d..ffb840a 100644 --- a/src/controller/user.router.js +++ b/src/controller/user.router.js @@ -1,7 +1,6 @@ const router = require("express").Router(); const controller = require("./user.controller"); -const { AuthenticateMiddleware } = require("../config/auth"); -const { SuperAdminCheck } = require("./utils/authorize"); +const { SuperAdminCheck, AuthenticateMiddleware } = require("./utils/authorize"); router.post("/register", controller.registerUser); router.post("/login", controller.loginUser); diff --git a/src/controller/utils/authorize.js b/src/controller/utils/authorize.js index 4c17cdc..ea92041 100644 --- a/src/controller/utils/authorize.js +++ b/src/controller/utils/authorize.js @@ -1,11 +1,44 @@ +const jwt = require("jsonwebtoken"); +const User = require("../../models/User"); const UserRole = require("../../models/UserRole"); -const { AuthorizeUser } = require("../../config/auth"); -const { SUPER_ADMIN_ROLE, AUTHORIZATION_FAILURE_ERROR_MESSAGE } = require("../../config/constants"); +const { + SUPER_ADMIN_ROLE, + AUTHORIZATION_FAILURE_ERROR_MESSAGE, +} = require("../../config/constants"); +const { JWT_SECRET } = require("../../config/env"); +const constants = require("../../config/constants"); + +const authenticate = async (token) => { + const decodedToken = jwt.verify(token, JWT_SECRET); + if (decodedToken) { + return await User.findById(decodedToken.id) + .populate({ path: "roles", populate: "permissions" }) + .populate("permissions"); + } +}; + +const authorize = async ( + user, + requiredRoles = [], + requiredPermissions = [] +) => { + const userRoles = user.roles.map((_) => _._id); + const userPermissions = [ + ...user.permissions.map((_) => _._id), + ...userRoles.map((_) => _.permissions).flat(), + ]; + + return ( + user != undefined && + requiredRoles.every((_) => userRoles.includes(_)) && + requiredPermissions.every((_) => userPermissions.includes(_)) + ); +}; module.exports = { SuperAdminCheck: async (req, res, next) => { const SuperAdmin = await UserRole.findOne({ name: SUPER_ADMIN_ROLE }); - if (AuthorizeUser(req.locals.user, [SuperAdmin.id])) { + if (authorize(req.locals.user, [SuperAdmin.id])) { next(); } else { res @@ -13,4 +46,23 @@ module.exports = { .send({ success: false, error: AUTHORIZATION_FAILURE_ERROR_MESSAGE }); } }, + AuthenticateMiddleware: async (req, res, next) => { + try { + const token = req.headers.authorization || ""; + if (token) { + const user = authenticate(token); + res.locals.user = user; + next(); + } else { + throw new Error("Not Authenticated user!"); + } + } catch (error) { + res.status(401).send({ + success: false, + error: constants.AUTHENTICATION_FAILURE_ERROR_MESSAGE, + }); + } + }, + + AuthorizeUser: authorize, }; diff --git a/src/controller/utils/sublevel.js b/src/controller/utils/sublevel.js index 9fcca0b..7f44a85 100644 --- a/src/controller/utils/sublevel.js +++ b/src/controller/utils/sublevel.js @@ -1,4 +1,4 @@ -const SubLevel = require("../../models/Sublevel"); +const Sublevel = require("../../models/Sublevel"); const Level = require("../../models/Level"); // exports.moveSublevel = async (sub_level_id, under_sub_or_level_id, isMainLevel) => { @@ -10,7 +10,7 @@ exports.deleteSubLevelTreeFromRoot = async (root_sub_level_id) => { let temp_sub_level_ids = [root_sub_level_id]; while (temp_sub_level_ids.length > 0) { - const level_sub_level_data = await SubLevel.find({ + const level_sub_level_data = await Sublevel.find({ _id: temp_sub_level_ids, }); @@ -24,7 +24,7 @@ exports.deleteSubLevelTreeFromRoot = async (root_sub_level_id) => { }); } - await SubLevel.deleteMany({ _id: sub_level_ids }); + await Sublevel.deleteMany({ _id: sub_level_ids }); console.log("Deleting sub-level tree", { sub_level_ids }); return sub_level_ids; }; diff --git a/src/controller/warehouse.controller.js b/src/controller/warehouse.controller.js index 4acf1a0..968cd36 100644 --- a/src/controller/warehouse.controller.js +++ b/src/controller/warehouse.controller.js @@ -55,6 +55,28 @@ module.exports = { } }, + /** + * Upload an image for the warehouse + */ + addWarehouseImage: async (req, res, next) => { + console.dir("Warehouse image uploaded:", { file: req.file }); + + const { id } = req.params; + + try { + const warehouseDetails = await Warehouse.findById(id); + if (!warehouseDetails) { + res.send({ success: false, message: "ID not found" }); + return; + } + warehouseDetails.imageUrl = req.file.path; + await warehouseDetails.save(); + res.send({ success: true, data: warehouseDetails }); + } catch (err) { + next(err); + } + }, + /** * Update a warehouses detail */ diff --git a/src/controller/warehouse.router.js b/src/controller/warehouse.router.js index 98b4dc7..cd8bf99 100644 --- a/src/controller/warehouse.router.js +++ b/src/controller/warehouse.router.js @@ -1,4 +1,5 @@ const router = require("express").Router(); +const upload = require("../middleware/fileUpload"); const controller = require("./warehouse.controller"); /** @@ -11,6 +12,15 @@ router.get("/:id", controller.getWarehouseByID); */ router.post("/", controller.createWarehouse); +/** + * @route /warehouse/add-image + */ +router.post( + "/add-image/:id", + upload.single("warehouse-image"), + controller.addWarehouseImage +); + /** * @route /warehouse/ */ diff --git a/src/middleware/fileUpload.js b/src/middleware/fileUpload.js new file mode 100644 index 0000000..e26d9ca --- /dev/null +++ b/src/middleware/fileUpload.js @@ -0,0 +1,33 @@ +const multer = require("multer"); + +const storage = multer.diskStorage({ + // multers disk storage settings + destination: function (req, file, cb) { + cb(null, "./uploads/"); + }, + limits: { + // files: 1, // Limit number of file uploads, if needed + fileSize: 1024 * 1024, + }, + filename: function (req, file, cb) { + cb( + null, + file.fieldname + "-" + Date.now() + "." + file.originalname.split(".")[file.originalname.split(".").length - 1] + ); + }, + onFileUploadStart: function (file) { + if (file.mimetype == "image/jpg" || file.mimetype == "image/jpeg" || file.mimetype == "image/png") { + return true; + } else { + return false; + } + }, +}); + +const upload = multer({ + // multer settings + storage, +}); + +// http://expressjs.com/en/resources/middleware/multer.html +module.exports = upload; diff --git a/src/models/Item.js b/src/models/Item.js index 1d83044..6835345 100644 --- a/src/models/Item.js +++ b/src/models/Item.js @@ -18,6 +18,11 @@ const schema = new mongoose.Schema( required: true, trim: true, }, + material: { + type: mongoose.Schema.Types.ObjectId, + ref: "Material", + required: true, + }, manufacturer: { type: String, required: true, @@ -47,10 +52,6 @@ const schema = new mongoose.Schema( type: Number, required: true, }, - unitQuantity: { - type: Number, - required: true, - }, packageCount: { type: Number, required: true, diff --git a/src/models/Material.js b/src/models/Material.js index 4aaf280..3f39983 100644 --- a/src/models/Material.js +++ b/src/models/Material.js @@ -7,21 +7,15 @@ const schema = new mongoose.Schema( required: true, trim: true, }, - family: [ - { - name: { - type: String, - required: true, - trim: true, - }, - depth: { - type: Number, - required: true, - min: 1, - max: 10 - }, - }, - ], + parent: { + type: mongoose.Schema.Types.ObjectId, + ref: "Material", + }, + inventory: { + type: mongoose.Schema.Types.ObjectId, + ref: "Inventory", + required: true + }, }, { timestamps: true, diff --git a/src/models/Sublevel.js b/src/models/Sublevel.js index b9cde4e..9873d87 100644 --- a/src/models/Sublevel.js +++ b/src/models/Sublevel.js @@ -68,12 +68,7 @@ const schema = new mongoose.Schema( } ); -schema.pre("save", function (next) { - // const sublevel = this; - // // write validation here? - next(); -}); +const Sublevel = mongoose.model("Sublevel", schema); -const SubLevel = mongoose.model("SubLevel", schema); +module.exports = Sublevel; -module.exports = SubLevel;