mirror of
https://github.com/sasjs/server.git
synced 2025-12-10 11:24:35 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c19a20c1d4 | ||
|
|
f8eaadae7b | ||
| 90e0973a7f | |||
| 869a13fc69 | |||
|
|
6d12b900ad | ||
|
|
ae5aa02733 | ||
|
|
28a6a36bb7 | ||
|
|
4e7579dc10 | ||
| 6b0b94ad38 | |||
|
|
b81d742c6c | ||
|
|
a61adbcac2 | ||
|
|
12000f4fc7 | ||
| 73792fb574 |
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,3 +1,29 @@
|
||||
# [0.6.0](https://github.com/sasjs/server/compare/v0.5.0...v0.6.0) (2022-06-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* get group by group name ([6b0b94a](https://github.com/sasjs/server/commit/6b0b94ad38215ae58e62279a4f73ac3ed2d9d0e8))
|
||||
|
||||
# [0.5.0](https://github.com/sasjs/server/compare/v0.4.2...v0.5.0) (2022-06-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* npm audit fix to avoid warnings on npm i ([28a6a36](https://github.com/sasjs/server/commit/28a6a36bb708b93fb5c2b74d587e9b2e055582be))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **api:** deployment through zipped/compressed file ([b81d742](https://github.com/sasjs/server/commit/b81d742c6c70d4cf1cab365b0e3efc087441db00))
|
||||
|
||||
## [0.4.2](https://github.com/sasjs/server/compare/v0.4.1...v0.4.2) (2022-06-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* appStream redesign ([73792fb](https://github.com/sasjs/server/commit/73792fb574c90bd280c4324e0b41c6fee7d572b6))
|
||||
|
||||
## [0.4.1](https://github.com/sasjs/server/compare/v0.4.0...v0.4.1) (2022-06-15)
|
||||
|
||||
|
||||
|
||||
384
api/package-lock.json
generated
384
api/package-lock.json
generated
@@ -25,12 +25,14 @@
|
||||
"morgan": "^1.10.0",
|
||||
"multer": "^1.4.3",
|
||||
"swagger-ui-express": "4.3.0",
|
||||
"unzipper": "^0.10.11",
|
||||
"url": "^0.10.3"
|
||||
},
|
||||
"bin": {
|
||||
"api": "build/src/server.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.5.0",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/cors": "^2.8.12",
|
||||
@@ -45,6 +47,8 @@
|
||||
"@types/node": "^15.12.2",
|
||||
"@types/supertest": "^2.0.11",
|
||||
"@types/swagger-ui-express": "^4.1.3",
|
||||
"@types/unzipper": "^0.10.5",
|
||||
"adm-zip": "^0.5.9",
|
||||
"dotenv": "^10.0.0",
|
||||
"http-headers-validation": "^0.0.1",
|
||||
"jest": "^27.0.6",
|
||||
@@ -1753,6 +1757,15 @@
|
||||
"yarn": ">=1.9.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/adm-zip": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz",
|
||||
"integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.1.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz",
|
||||
@@ -2176,6 +2189,15 @@
|
||||
"integrity": "sha512-MhSa0yylXtVMsyT8qFpHA1DLHj4DvQGH5ntxrhHSh8PxUVNi35Wk+P5hVgqbO2qZqOotqr9jaoPRL+iRjWYm/A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/unzipper": {
|
||||
"version": "0.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/unzipper/-/unzipper-0.10.5.tgz",
|
||||
"integrity": "sha512-NrLJb29AdnBARpg9S/4ktfPEisbJ0AvaaAr3j7Q1tg8AgcEUsq2HqbNzvgLRoWyRtjzeLEv7vuL39u1mrNIyNA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webidl-conversions": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
|
||||
@@ -2272,6 +2294,15 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/adm-zip": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
|
||||
"integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
@@ -2684,6 +2715,26 @@
|
||||
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
|
||||
"integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
|
||||
},
|
||||
"node_modules/big-integer": {
|
||||
"version": "1.6.51",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
|
||||
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/binary": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
|
||||
"integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
|
||||
"dependencies": {
|
||||
"buffers": "~0.1.1",
|
||||
"chainsaw": "~0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
@@ -2710,6 +2761,11 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.4.7",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
|
||||
"integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA=="
|
||||
},
|
||||
"node_modules/bn.js": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||
@@ -2881,6 +2937,22 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||
},
|
||||
"node_modules/buffer-indexof-polyfill": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
|
||||
"integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/buffers": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
|
||||
"integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==",
|
||||
"engines": {
|
||||
"node": ">=0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
|
||||
@@ -3011,6 +3083,17 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/chainsaw": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
|
||||
"integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
|
||||
"dependencies": {
|
||||
"traverse": ">=0.3.0 <0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||
@@ -3780,6 +3863,36 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
"integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
|
||||
"dependencies": {
|
||||
"readable-stream": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer2/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/duplexer2/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/duplexer3": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
|
||||
@@ -4450,6 +4563,42 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fstream": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
|
||||
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"inherits": "~2.0.0",
|
||||
"mkdirp": ">=0.5 0",
|
||||
"rimraf": "2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fstream/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/fstream/node_modules/rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@@ -7064,6 +7213,11 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/listenercount": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
|
||||
"integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ=="
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
@@ -8910,6 +9064,11 @@
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
@@ -9648,6 +9807,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/traverse": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
||||
"integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/traverse-chain": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz",
|
||||
@@ -9926,6 +10093,45 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/unzipper": {
|
||||
"version": "0.10.11",
|
||||
"resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz",
|
||||
"integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==",
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.17",
|
||||
"binary": "~0.3.0",
|
||||
"bluebird": "~3.4.1",
|
||||
"buffer-indexof-polyfill": "~1.0.0",
|
||||
"duplexer2": "~0.1.4",
|
||||
"fstream": "^1.0.12",
|
||||
"graceful-fs": "^4.2.2",
|
||||
"listenercount": "~1.0.1",
|
||||
"readable-stream": "~2.3.6",
|
||||
"setimmediate": "~1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/unzipper/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/unzipper/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/update-notifier": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz",
|
||||
@@ -11700,6 +11906,15 @@
|
||||
"validator": "^13.6.0"
|
||||
}
|
||||
},
|
||||
"@types/adm-zip": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz",
|
||||
"integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/babel__core": {
|
||||
"version": "7.1.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz",
|
||||
@@ -12097,6 +12312,15 @@
|
||||
"integrity": "sha512-MhSa0yylXtVMsyT8qFpHA1DLHj4DvQGH5ntxrhHSh8PxUVNi35Wk+P5hVgqbO2qZqOotqr9jaoPRL+iRjWYm/A==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/unzipper": {
|
||||
"version": "0.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/unzipper/-/unzipper-0.10.5.tgz",
|
||||
"integrity": "sha512-NrLJb29AdnBARpg9S/4ktfPEisbJ0AvaaAr3j7Q1tg8AgcEUsq2HqbNzvgLRoWyRtjzeLEv7vuL39u1mrNIyNA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/webidl-conversions": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
|
||||
@@ -12177,6 +12401,12 @@
|
||||
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
|
||||
"dev": true
|
||||
},
|
||||
"adm-zip": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
|
||||
"integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==",
|
||||
"dev": true
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
@@ -12500,6 +12730,20 @@
|
||||
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
|
||||
"integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
|
||||
},
|
||||
"big-integer": {
|
||||
"version": "1.6.51",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
|
||||
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg=="
|
||||
},
|
||||
"binary": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
|
||||
"integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
|
||||
"requires": {
|
||||
"buffers": "~0.1.1",
|
||||
"chainsaw": "~0.1.0"
|
||||
}
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
@@ -12525,6 +12769,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.4.7",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
|
||||
"integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA=="
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||
@@ -12651,6 +12900,16 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||
},
|
||||
"buffer-indexof-polyfill": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
|
||||
"integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A=="
|
||||
},
|
||||
"buffers": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
|
||||
"integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ=="
|
||||
},
|
||||
"busboy": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
|
||||
@@ -12748,6 +13007,14 @@
|
||||
"integrity": "sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==",
|
||||
"dev": true
|
||||
},
|
||||
"chainsaw": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
|
||||
"integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
|
||||
"requires": {
|
||||
"traverse": ">=0.3.0 <0.4"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||
@@ -13374,6 +13641,38 @@
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
|
||||
"dev": true
|
||||
},
|
||||
"duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
"integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"duplexer3": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
|
||||
@@ -13896,6 +14195,35 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"fstream": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
|
||||
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"inherits": "~2.0.0",
|
||||
"mkdirp": ">=0.5 0",
|
||||
"rimraf": "2"
|
||||
},
|
||||
"dependencies": {
|
||||
"mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.6"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@@ -15839,6 +16167,11 @@
|
||||
"type-check": "~0.3.2"
|
||||
}
|
||||
},
|
||||
"listenercount": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
|
||||
"integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ=="
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
@@ -17219,6 +17552,11 @@
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||
"dev": true
|
||||
},
|
||||
"setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
@@ -17785,6 +18123,11 @@
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"traverse": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
||||
"integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ=="
|
||||
},
|
||||
"traverse-chain": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz",
|
||||
@@ -17972,6 +18315,47 @@
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||
},
|
||||
"unzipper": {
|
||||
"version": "0.10.11",
|
||||
"resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz",
|
||||
"integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.17",
|
||||
"binary": "~0.3.0",
|
||||
"bluebird": "~3.4.1",
|
||||
"buffer-indexof-polyfill": "~1.0.0",
|
||||
"duplexer2": "~0.1.4",
|
||||
"fstream": "^1.0.12",
|
||||
"graceful-fs": "^4.2.2",
|
||||
"listenercount": "~1.0.1",
|
||||
"readable-stream": "~2.3.6",
|
||||
"setimmediate": "~1.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"update-notifier": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz",
|
||||
|
||||
@@ -64,9 +64,11 @@
|
||||
"morgan": "^1.10.0",
|
||||
"multer": "^1.4.3",
|
||||
"swagger-ui-express": "4.3.0",
|
||||
"unzipper": "^0.10.11",
|
||||
"url": "^0.10.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.5.0",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/cors": "^2.8.12",
|
||||
@@ -81,6 +83,8 @@
|
||||
"@types/node": "^15.12.2",
|
||||
"@types/supertest": "^2.0.11",
|
||||
"@types/swagger-ui-express": "^4.1.3",
|
||||
"@types/unzipper": "^0.10.5",
|
||||
"adm-zip": "^0.5.9",
|
||||
"dotenv": "^10.0.0",
|
||||
"http-headers-validation": "^0.0.1",
|
||||
"jest": "^27.0.6",
|
||||
|
||||
@@ -425,6 +425,27 @@ components:
|
||||
- description
|
||||
type: object
|
||||
additionalProperties: false
|
||||
_LeanDocument__LeanDocument_T__:
|
||||
properties: {}
|
||||
type: object
|
||||
Pick__LeanDocument_T_.Exclude_keyof_LeanDocument_T_.Exclude_keyofDocument._id-or-id-or-__v_-or-%24isSingleNested__:
|
||||
properties:
|
||||
id:
|
||||
description: 'The string version of this documents _id.'
|
||||
_id:
|
||||
$ref: '#/components/schemas/_LeanDocument__LeanDocument_T__'
|
||||
description: 'This documents _id.'
|
||||
__v:
|
||||
description: 'This documents __v.'
|
||||
type: object
|
||||
description: 'From T, pick a set of properties whose keys are in the union K'
|
||||
Omit__LeanDocument_this_.Exclude_keyofDocument._id-or-id-or-__v_-or-%24isSingleNested_:
|
||||
$ref: '#/components/schemas/Pick__LeanDocument_T_.Exclude_keyof_LeanDocument_T_.Exclude_keyofDocument._id-or-id-or-__v_-or-%24isSingleNested__'
|
||||
description: 'Construct a type with the properties of T except for those in type K.'
|
||||
LeanDocument_this_:
|
||||
$ref: '#/components/schemas/Omit__LeanDocument_this_.Exclude_keyofDocument._id-or-id-or-__v_-or-%24isSingleNested_'
|
||||
IGroup:
|
||||
$ref: '#/components/schemas/LeanDocument_this_'
|
||||
InfoResponse:
|
||||
properties:
|
||||
mode:
|
||||
@@ -727,7 +748,8 @@ paths:
|
||||
examples:
|
||||
'Example 1':
|
||||
value: {status: failure, message: 'Deployment failed!'}
|
||||
summary: 'Creates/updates files within SASjs Drive using uploaded JSON file.'
|
||||
description: "Accepts JSON file and zipped compressed JSON file as well.\nCompressed file should only contain one JSON file and should have same name\nas of compressed file e.g. deploy.JSON should be compressed to deploy.JSON.zip\nAny other file or JSON file in zipped will be ignored!"
|
||||
summary: 'Creates/updates files within SASjs Drive using uploaded JSON/compressed JSON file.'
|
||||
tags:
|
||||
- Drive
|
||||
security:
|
||||
@@ -1215,6 +1237,30 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GroupPayload'
|
||||
'/SASjsApi/group/by/groupname/{name}':
|
||||
get:
|
||||
operationId: GetGroupByGroupName
|
||||
responses:
|
||||
'200':
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GroupDetailsResponse'
|
||||
summary: 'Get list of members of a group (userName). All users can request this.'
|
||||
tags:
|
||||
- Group
|
||||
security:
|
||||
-
|
||||
bearerAuth: []
|
||||
parameters:
|
||||
-
|
||||
description: 'The group''s name'
|
||||
in: path
|
||||
name: name
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
'/SASjsApi/group/{groupId}':
|
||||
get:
|
||||
operationId: GetGroup
|
||||
@@ -1244,8 +1290,14 @@ paths:
|
||||
delete:
|
||||
operationId: DeleteGroup
|
||||
responses:
|
||||
'204':
|
||||
description: 'No content'
|
||||
'200':
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- {$ref: '#/components/schemas/IGroup'}
|
||||
- {properties: {_id: {}}, required: [_id], type: object}
|
||||
summary: 'Delete a group. Admin task only.'
|
||||
tags:
|
||||
- Group
|
||||
|
||||
@@ -96,7 +96,12 @@ export class DriveController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Creates/updates files within SASjs Drive using uploaded JSON file.
|
||||
* Accepts JSON file and zipped compressed JSON file as well.
|
||||
* Compressed file should only contain one JSON file and should have same name
|
||||
* as of compressed file e.g. deploy.JSON should be compressed to deploy.JSON.zip
|
||||
* Any other file or JSON file in zipped will be ignored!
|
||||
*
|
||||
* @summary Creates/updates files within SASjs Drive using uploaded JSON/compressed JSON file.
|
||||
*
|
||||
*/
|
||||
@Example<DeployResponse>(successDeployResponse)
|
||||
|
||||
@@ -28,6 +28,11 @@ interface GroupDetailsResponse {
|
||||
users: UserResponse[]
|
||||
}
|
||||
|
||||
interface GetGroupBy {
|
||||
groupId?: number
|
||||
name?: string
|
||||
}
|
||||
|
||||
@Security('bearerAuth')
|
||||
@Route('SASjsApi/group')
|
||||
@Tags('Group')
|
||||
@@ -66,6 +71,18 @@ export class GroupController {
|
||||
return createGroup(body)
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get list of members of a group (userName). All users can request this.
|
||||
* @param name The group's name
|
||||
* @example dcgroup
|
||||
*/
|
||||
@Get('by/groupname/{name}')
|
||||
public async getGroupByGroupName(
|
||||
@Path() name: string
|
||||
): Promise<GroupDetailsResponse> {
|
||||
return getGroup({ name })
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get list of members of a group (userName). All users can request this.
|
||||
* @param groupId The group's identifier
|
||||
@@ -75,7 +92,7 @@ export class GroupController {
|
||||
public async getGroup(
|
||||
@Path() groupId: number
|
||||
): Promise<GroupDetailsResponse> {
|
||||
return getGroup(groupId)
|
||||
return getGroup({ groupId })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,9 +146,13 @@ export class GroupController {
|
||||
*/
|
||||
@Delete('{groupId}')
|
||||
public async deleteGroup(@Path() groupId: number) {
|
||||
const { deletedCount } = await Group.deleteOne({ groupId })
|
||||
if (deletedCount) return
|
||||
throw new Error('No Group deleted!')
|
||||
const group = await Group.findOne({ groupId })
|
||||
if (group) return await group.remove()
|
||||
throw {
|
||||
code: 404,
|
||||
status: 'Not Found',
|
||||
message: 'Group not found.'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +166,15 @@ const createGroup = async ({
|
||||
description,
|
||||
isActive
|
||||
}: GroupPayload): Promise<GroupDetailsResponse> => {
|
||||
// Checking if user is already in the database
|
||||
const groupnameExist = await Group.findOne({ name })
|
||||
if (groupnameExist)
|
||||
throw {
|
||||
code: 409,
|
||||
status: 'Conflict',
|
||||
message: 'Group name already exists.'
|
||||
}
|
||||
|
||||
const group = new Group({
|
||||
name,
|
||||
description,
|
||||
@@ -162,15 +192,20 @@ const createGroup = async ({
|
||||
}
|
||||
}
|
||||
|
||||
const getGroup = async (groupId: number): Promise<GroupDetailsResponse> => {
|
||||
const getGroup = async (findBy: GetGroupBy): Promise<GroupDetailsResponse> => {
|
||||
const group = (await Group.findOne(
|
||||
{ groupId },
|
||||
findBy,
|
||||
'groupId name description isActive users -_id'
|
||||
).populate(
|
||||
'users',
|
||||
'id username displayName -_id'
|
||||
)) as unknown as GroupDetailsResponse
|
||||
if (!group) throw new Error('Group not found.')
|
||||
if (!group)
|
||||
throw {
|
||||
code: 404,
|
||||
status: 'Not Found',
|
||||
message: 'Group not found.'
|
||||
}
|
||||
|
||||
return {
|
||||
groupId: group.groupId,
|
||||
@@ -199,16 +234,31 @@ const updateUsersListInGroup = async (
|
||||
action: 'addUser' | 'removeUser'
|
||||
): Promise<GroupDetailsResponse> => {
|
||||
const group = await Group.findOne({ groupId })
|
||||
if (!group) throw new Error('Group not found.')
|
||||
if (!group)
|
||||
throw {
|
||||
code: 404,
|
||||
status: 'Not Found',
|
||||
message: 'Group not found.'
|
||||
}
|
||||
|
||||
const user = await User.findOne({ id: userId })
|
||||
if (!user) throw new Error('User not found.')
|
||||
if (!user)
|
||||
throw {
|
||||
code: 404,
|
||||
status: 'Not Found',
|
||||
message: 'User not found.'
|
||||
}
|
||||
|
||||
const updatedGroup = (action === 'addUser'
|
||||
? await group.addUser(user._id)
|
||||
: await group.removeUser(user._id)) as unknown as GroupDetailsResponse
|
||||
|
||||
if (!updatedGroup) throw new Error('Unable to update group')
|
||||
if (!updatedGroup)
|
||||
throw {
|
||||
code: 400,
|
||||
status: 'Bad Request',
|
||||
message: 'Unable to update group.'
|
||||
}
|
||||
|
||||
if (action === 'addUser') user.addGroup(group._id)
|
||||
else user.removeGroup(group._id)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import mongoose, { Schema, model, Document, Model } from 'mongoose'
|
||||
import User from './User'
|
||||
const AutoIncrement = require('mongoose-sequence')(mongoose)
|
||||
|
||||
export interface GroupPayload {
|
||||
@@ -34,7 +35,8 @@ interface IGroupModel extends Model<IGroup> {}
|
||||
const groupSchema = new Schema<IGroupDocument>({
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
@@ -46,6 +48,7 @@ const groupSchema = new Schema<IGroupDocument>({
|
||||
},
|
||||
users: [{ type: Schema.Types.ObjectId, ref: 'User' }]
|
||||
})
|
||||
|
||||
groupSchema.plugin(AutoIncrement, { inc_field: 'groupId' })
|
||||
|
||||
// Hooks
|
||||
@@ -55,6 +58,17 @@ groupSchema.post('save', function (group: IGroup, next: Function) {
|
||||
})
|
||||
})
|
||||
|
||||
// pre remove hook to remove all references of group from users
|
||||
groupSchema.pre('remove', async function () {
|
||||
const userIds = this.users
|
||||
await Promise.all(
|
||||
userIds.map(async (userId) => {
|
||||
const user = await User.findById(userId)
|
||||
user?.removeGroup(this._id)
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
// Instance Methods
|
||||
groupSchema.method(
|
||||
'addUser',
|
||||
|
||||
@@ -7,9 +7,12 @@ import { multerSingle } from '../../middlewares/multer'
|
||||
import { DriveController } from '../../controllers/'
|
||||
import {
|
||||
deployValidation,
|
||||
extractJSONFromZip,
|
||||
extractName,
|
||||
fileBodyValidation,
|
||||
fileParamValidation,
|
||||
folderParamValidation
|
||||
folderParamValidation,
|
||||
isZipFile
|
||||
} from '../../utils'
|
||||
|
||||
const controller = new DriveController()
|
||||
@@ -49,7 +52,24 @@ driveRouter.post(
|
||||
async (req, res) => {
|
||||
if (!req.file) return res.status(400).send('"file" is not present.')
|
||||
|
||||
const fileContent = await readFile(req.file.path)
|
||||
let fileContent: string = ''
|
||||
|
||||
const { value: zipFile } = isZipFile(req.file)
|
||||
if (zipFile) {
|
||||
fileContent = await extractJSONFromZip(zipFile)
|
||||
const fileInZip = extractName(zipFile.originalname)
|
||||
|
||||
if (!fileContent) {
|
||||
deleteFile(req.file.path)
|
||||
return res
|
||||
.status(400)
|
||||
.send(
|
||||
`No content present in ${fileInZip} of compressed file ${zipFile.originalname}`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
fileContent = await readFile(req.file.path)
|
||||
}
|
||||
|
||||
let jsonContent
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import express from 'express'
|
||||
import { GroupController } from '../../controllers/'
|
||||
import { authenticateAccessToken, verifyAdmin } from '../../middlewares'
|
||||
import { registerGroupValidation } from '../../utils'
|
||||
import { getGroupValidation, registerGroupValidation } from '../../utils'
|
||||
|
||||
const groupRouter = express.Router()
|
||||
|
||||
@@ -18,7 +18,11 @@ groupRouter.post(
|
||||
const response = await controller.createGroup(body)
|
||||
res.send(response)
|
||||
} catch (err: any) {
|
||||
res.status(403).send(err.toString())
|
||||
const statusCode = err.code
|
||||
|
||||
delete err.code
|
||||
|
||||
res.status(statusCode).send(err.message)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -29,7 +33,11 @@ groupRouter.get('/', authenticateAccessToken, async (req, res) => {
|
||||
const response = await controller.getAllGroups()
|
||||
res.send(response)
|
||||
} catch (err: any) {
|
||||
res.status(403).send(err.toString())
|
||||
const statusCode = err.code
|
||||
|
||||
delete err.code
|
||||
|
||||
res.status(statusCode).send(err.message)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -41,10 +49,37 @@ groupRouter.get('/:groupId', authenticateAccessToken, async (req, res) => {
|
||||
const response = await controller.getGroup(parseInt(groupId))
|
||||
res.send(response)
|
||||
} catch (err: any) {
|
||||
res.status(403).send(err.toString())
|
||||
const statusCode = err.code
|
||||
|
||||
delete err.code
|
||||
|
||||
res.status(statusCode).send(err.message)
|
||||
}
|
||||
})
|
||||
|
||||
groupRouter.get(
|
||||
'/by/groupname/:name',
|
||||
authenticateAccessToken,
|
||||
async (req, res) => {
|
||||
const { error, value: params } = getGroupValidation(req.params)
|
||||
if (error) return res.status(400).send(error.details[0].message)
|
||||
|
||||
const { name } = params
|
||||
|
||||
const controller = new GroupController()
|
||||
try {
|
||||
const response = await controller.getGroupByGroupName(name)
|
||||
res.send(response)
|
||||
} catch (err: any) {
|
||||
const statusCode = err.code
|
||||
|
||||
delete err.code
|
||||
|
||||
res.status(statusCode).send(err.message)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
groupRouter.post(
|
||||
'/:groupId/:userId',
|
||||
authenticateAccessToken,
|
||||
@@ -60,7 +95,11 @@ groupRouter.post(
|
||||
)
|
||||
res.send(response)
|
||||
} catch (err: any) {
|
||||
res.status(403).send(err.toString())
|
||||
const statusCode = err.code
|
||||
|
||||
delete err.code
|
||||
|
||||
res.status(statusCode).send(err.message)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -80,7 +119,11 @@ groupRouter.delete(
|
||||
)
|
||||
res.send(response)
|
||||
} catch (err: any) {
|
||||
res.status(403).send(err.toString())
|
||||
const statusCode = err.code
|
||||
|
||||
delete err.code
|
||||
|
||||
res.status(statusCode).send(err.message)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -97,7 +140,11 @@ groupRouter.delete(
|
||||
await controller.deleteGroup(parseInt(groupId))
|
||||
res.status(200).send('Group Deleted!')
|
||||
} catch (err: any) {
|
||||
res.status(403).send(err.toString())
|
||||
const statusCode = err.code
|
||||
|
||||
delete err.code
|
||||
|
||||
res.status(statusCode).send(err.message)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Express } from 'express'
|
||||
import mongoose, { Mongoose } from 'mongoose'
|
||||
import { MongoMemoryServer } from 'mongodb-memory-server'
|
||||
import request from 'supertest'
|
||||
import AdmZip from 'adm-zip'
|
||||
|
||||
import {
|
||||
folderExists,
|
||||
@@ -72,11 +73,52 @@ describe('drive', () => {
|
||||
})
|
||||
|
||||
describe('deploy', () => {
|
||||
const shouldFailAssertion = async (payload: any) => {
|
||||
const res = await request(app)
|
||||
.post('/SASjsApi/drive/deploy')
|
||||
.auth(accessToken, { type: 'bearer' })
|
||||
.send({ appLoc: '/Public', fileTree: payload })
|
||||
const makeRequest = async (payload: any, type: string = 'payload') => {
|
||||
const requestUrl =
|
||||
type === 'payload'
|
||||
? '/SASjsApi/drive/deploy'
|
||||
: '/SASjsApi/drive/deploy/upload'
|
||||
|
||||
if (type === 'payload') {
|
||||
return await request(app)
|
||||
.post(requestUrl)
|
||||
.auth(accessToken, { type: 'bearer' })
|
||||
.send({ appLoc: '/Public', fileTree: payload })
|
||||
}
|
||||
if (type === 'file') {
|
||||
const deployContents = JSON.stringify({
|
||||
appLoc: '/Public',
|
||||
fileTree: payload
|
||||
})
|
||||
return await request(app)
|
||||
.post(requestUrl)
|
||||
.auth(accessToken, { type: 'bearer' })
|
||||
.attach('file', Buffer.from(deployContents), 'deploy.json')
|
||||
} else {
|
||||
const deployContents = JSON.stringify({
|
||||
appLoc: '/Public',
|
||||
fileTree: payload
|
||||
})
|
||||
const zip = new AdmZip()
|
||||
// add file directly
|
||||
zip.addFile(
|
||||
'deploy.json',
|
||||
Buffer.from(deployContents, 'utf8'),
|
||||
'entry comment goes here'
|
||||
)
|
||||
|
||||
return await request(app)
|
||||
.post(requestUrl)
|
||||
.auth(accessToken, { type: 'bearer' })
|
||||
.attach('file', zip.toBuffer(), 'deploy.json.zip')
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFailAssertion = async (
|
||||
payload: any,
|
||||
type: string = 'payload'
|
||||
) => {
|
||||
const res = await makeRequest(payload, type)
|
||||
|
||||
expect(res.statusCode).toEqual(400)
|
||||
|
||||
@@ -176,6 +218,240 @@ describe('drive', () => {
|
||||
|
||||
await deleteFolder(path.join(getFilesFolder(), 'public'))
|
||||
})
|
||||
|
||||
describe('upload', () => {
|
||||
it('should respond with payload example if valid JSON file was not provided', async () => {
|
||||
await shouldFailAssertion(null, 'file')
|
||||
await shouldFailAssertion(undefined, 'file')
|
||||
await shouldFailAssertion('data', 'file')
|
||||
await shouldFailAssertion({}, 'file')
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
userId: 1,
|
||||
title: 'test is cool'
|
||||
},
|
||||
'file'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
membersWRONG: []
|
||||
},
|
||||
'file'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: {}
|
||||
},
|
||||
'file'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: [
|
||||
{
|
||||
nameWRONG: 'jobs',
|
||||
type: 'folder',
|
||||
members: []
|
||||
}
|
||||
]
|
||||
},
|
||||
'file'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: [
|
||||
{
|
||||
name: 'jobs',
|
||||
type: 'WRONG',
|
||||
members: []
|
||||
}
|
||||
]
|
||||
},
|
||||
'file'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: [
|
||||
{
|
||||
name: 'jobs',
|
||||
type: 'folder',
|
||||
members: [
|
||||
{
|
||||
name: 'extract',
|
||||
type: 'folder',
|
||||
members: [
|
||||
{
|
||||
name: 'makedata1',
|
||||
type: 'service',
|
||||
codeWRONG: '%put Hello World!;'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
'file'
|
||||
)
|
||||
})
|
||||
|
||||
it('should successfully deploy if valid JSON file was provided', async () => {
|
||||
const deployContents = JSON.stringify({
|
||||
appLoc: '/public',
|
||||
fileTree: getTreeExample()
|
||||
})
|
||||
const res = await request(app)
|
||||
.post('/SASjsApi/drive/deploy/upload')
|
||||
.auth(accessToken, { type: 'bearer' })
|
||||
.attach('file', Buffer.from(deployContents), 'deploy.json')
|
||||
|
||||
expect(res.statusCode).toEqual(200)
|
||||
expect(res.text).toEqual(
|
||||
'{"status":"success","message":"Files deployed successfully to @sasjs/server."}'
|
||||
)
|
||||
await expect(folderExists(getFilesFolder())).resolves.toEqual(true)
|
||||
|
||||
const testJobFolder = path.join(
|
||||
getFilesFolder(),
|
||||
'public',
|
||||
'jobs',
|
||||
'extract'
|
||||
)
|
||||
await expect(folderExists(testJobFolder)).resolves.toEqual(true)
|
||||
|
||||
const exampleService = getExampleService()
|
||||
const testJobFile =
|
||||
path.join(testJobFolder, exampleService.name) + '.sas'
|
||||
|
||||
await expect(fileExists(testJobFile)).resolves.toEqual(true)
|
||||
|
||||
await expect(readFile(testJobFile)).resolves.toEqual(
|
||||
exampleService.code
|
||||
)
|
||||
|
||||
await deleteFolder(path.join(getFilesFolder(), 'public'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('upload - zipped', () => {
|
||||
it('should respond with payload example if valid Zipped file was not provided', async () => {
|
||||
await shouldFailAssertion(null, 'zip')
|
||||
await shouldFailAssertion(undefined, 'zip')
|
||||
await shouldFailAssertion('data', 'zip')
|
||||
await shouldFailAssertion({}, 'zip')
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
userId: 1,
|
||||
title: 'test is cool'
|
||||
},
|
||||
'zip'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
membersWRONG: []
|
||||
},
|
||||
'zip'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: {}
|
||||
},
|
||||
'zip'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: [
|
||||
{
|
||||
nameWRONG: 'jobs',
|
||||
type: 'folder',
|
||||
members: []
|
||||
}
|
||||
]
|
||||
},
|
||||
'zip'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: [
|
||||
{
|
||||
name: 'jobs',
|
||||
type: 'WRONG',
|
||||
members: []
|
||||
}
|
||||
]
|
||||
},
|
||||
'zip'
|
||||
)
|
||||
await shouldFailAssertion(
|
||||
{
|
||||
members: [
|
||||
{
|
||||
name: 'jobs',
|
||||
type: 'folder',
|
||||
members: [
|
||||
{
|
||||
name: 'extract',
|
||||
type: 'folder',
|
||||
members: [
|
||||
{
|
||||
name: 'makedata1',
|
||||
type: 'service',
|
||||
codeWRONG: '%put Hello World!;'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
'zip'
|
||||
)
|
||||
})
|
||||
|
||||
it('should successfully deploy if valid Zipped file was provided', async () => {
|
||||
const deployContents = JSON.stringify({
|
||||
appLoc: '/public',
|
||||
fileTree: getTreeExample()
|
||||
})
|
||||
|
||||
const zip = new AdmZip()
|
||||
// add file directly
|
||||
zip.addFile(
|
||||
'deploy.json',
|
||||
Buffer.from(deployContents, 'utf8'),
|
||||
'entry comment goes here'
|
||||
)
|
||||
const res = await request(app)
|
||||
.post('/SASjsApi/drive/deploy/upload')
|
||||
.auth(accessToken, { type: 'bearer' })
|
||||
.attach('file', zip.toBuffer(), 'deploy.json.zip')
|
||||
|
||||
expect(res.statusCode).toEqual(200)
|
||||
expect(res.text).toEqual(
|
||||
'{"status":"success","message":"Files deployed successfully to @sasjs/server."}'
|
||||
)
|
||||
await expect(folderExists(getFilesFolder())).resolves.toEqual(true)
|
||||
|
||||
const testJobFolder = path.join(
|
||||
getFilesFolder(),
|
||||
'public',
|
||||
'jobs',
|
||||
'extract'
|
||||
)
|
||||
await expect(folderExists(testJobFolder)).resolves.toEqual(true)
|
||||
|
||||
const exampleService = getExampleService()
|
||||
const testJobFile =
|
||||
path.join(testJobFolder, exampleService.name) + '.sas'
|
||||
|
||||
await expect(fileExists(testJobFile)).resolves.toEqual(true)
|
||||
|
||||
await expect(readFile(testJobFile)).resolves.toEqual(
|
||||
exampleService.code
|
||||
)
|
||||
|
||||
await deleteFolder(path.join(getFilesFolder(), 'public'))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('folder', () => {
|
||||
|
||||
@@ -23,7 +23,7 @@ const user = {
|
||||
}
|
||||
|
||||
const group = {
|
||||
name: 'DCGroup1',
|
||||
name: 'dcgroup1',
|
||||
description: 'DC group for testing purposes.'
|
||||
}
|
||||
|
||||
@@ -70,6 +70,32 @@ describe('group', () => {
|
||||
expect(res.body.users).toEqual([])
|
||||
})
|
||||
|
||||
it('should respond with Conflict when group already exists with same name', async () => {
|
||||
await groupController.createGroup(group)
|
||||
|
||||
const res = await request(app)
|
||||
.post('/SASjsApi/group')
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send(group)
|
||||
.expect(409)
|
||||
|
||||
expect(res.text).toEqual('Group name already exists.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Bad Request when group name does not match the group name schema', async () => {
|
||||
const res = await request(app)
|
||||
.post('/SASjsApi/group')
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send({ ...group, name: 'Wrong Group Name' })
|
||||
.expect(400)
|
||||
|
||||
expect(res.text).toEqual(
|
||||
'"name" must only contain alpha-numeric characters'
|
||||
)
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Unauthorized if access token is not present', async () => {
|
||||
const res = await request(app).post('/SASjsApi/group').send().expect(401)
|
||||
|
||||
@@ -125,14 +151,51 @@ describe('group', () => {
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Forbidden if groupId is incorrect', async () => {
|
||||
it(`should delete group's reference from users' groups array`, async () => {
|
||||
const dbGroup = await groupController.createGroup(group)
|
||||
const dbUser1 = await userController.createUser({
|
||||
...user,
|
||||
username: 'deletegroup1'
|
||||
})
|
||||
const dbUser2 = await userController.createUser({
|
||||
...user,
|
||||
username: 'deletegroup2'
|
||||
})
|
||||
|
||||
await groupController.addUserToGroup(dbGroup.groupId, dbUser1.id)
|
||||
await groupController.addUserToGroup(dbGroup.groupId, dbUser2.id)
|
||||
|
||||
await request(app)
|
||||
.delete(`/SASjsApi/group/${dbGroup.groupId}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
const res1 = await request(app)
|
||||
.get(`/SASjsApi/user/${dbUser1.id}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
expect(res1.body.groups).toEqual([])
|
||||
|
||||
const res2 = await request(app)
|
||||
.get(`/SASjsApi/user/${dbUser2.id}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
expect(res2.body.groups).toEqual([])
|
||||
})
|
||||
|
||||
it('should respond with Not Found if groupId is incorrect', async () => {
|
||||
const res = await request(app)
|
||||
.delete(`/SASjsApi/group/1234`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(403)
|
||||
.expect(404)
|
||||
|
||||
expect(res.text).toEqual('Error: No Group deleted!')
|
||||
expect(res.text).toEqual('Group not found.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
@@ -216,16 +279,76 @@ describe('group', () => {
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Forbidden if groupId is incorrect', async () => {
|
||||
it('should respond with Not Found if groupId is incorrect', async () => {
|
||||
const res = await request(app)
|
||||
.get('/SASjsApi/group/1234')
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(403)
|
||||
.expect(404)
|
||||
|
||||
expect(res.text).toEqual('Error: Group not found.')
|
||||
expect(res.text).toEqual('Group not found.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
describe('by group name', () => {
|
||||
it('should respond with group', async () => {
|
||||
const { name } = await groupController.createGroup(group)
|
||||
|
||||
const res = await request(app)
|
||||
.get(`/SASjsApi/group/by/groupname/${name}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
expect(res.body.groupId).toBeTruthy()
|
||||
expect(res.body.name).toEqual(group.name)
|
||||
expect(res.body.description).toEqual(group.description)
|
||||
expect(res.body.isActive).toEqual(true)
|
||||
expect(res.body.users).toEqual([])
|
||||
})
|
||||
|
||||
it('should respond with group when access token is not of an admin account', async () => {
|
||||
const accessToken = await generateSaveTokenAndCreateUser({
|
||||
...user,
|
||||
username: 'getbyname' + user.username
|
||||
})
|
||||
|
||||
const { name } = await groupController.createGroup(group)
|
||||
|
||||
const res = await request(app)
|
||||
.get(`/SASjsApi/group/by/groupname/${name}`)
|
||||
.auth(accessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
expect(res.body.groupId).toBeTruthy()
|
||||
expect(res.body.name).toEqual(group.name)
|
||||
expect(res.body.description).toEqual(group.description)
|
||||
expect(res.body.isActive).toEqual(true)
|
||||
expect(res.body.users).toEqual([])
|
||||
})
|
||||
|
||||
it('should respond with Unauthorized if access token is not present', async () => {
|
||||
const res = await request(app)
|
||||
.get('/SASjsApi/group/by/groupname/dcgroup')
|
||||
.send()
|
||||
.expect(401)
|
||||
|
||||
expect(res.text).toEqual('Unauthorized')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Not Found if groupname is incorrect', async () => {
|
||||
const res = await request(app)
|
||||
.get('/SASjsApi/group/by/groupname/randomCharacters')
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(404)
|
||||
|
||||
expect(res.text).toEqual('Group not found.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAll', () => {
|
||||
@@ -245,8 +368,8 @@ describe('group', () => {
|
||||
expect(res.body).toEqual([
|
||||
{
|
||||
groupId: expect.anything(),
|
||||
name: 'DCGroup1',
|
||||
description: 'DC group for testing purposes.'
|
||||
name: group.name,
|
||||
description: group.description
|
||||
}
|
||||
])
|
||||
})
|
||||
@@ -267,8 +390,8 @@ describe('group', () => {
|
||||
expect(res.body).toEqual([
|
||||
{
|
||||
groupId: expect.anything(),
|
||||
name: 'DCGroup1',
|
||||
description: 'DC group for testing purposes.'
|
||||
name: group.name,
|
||||
description: group.description
|
||||
}
|
||||
])
|
||||
})
|
||||
@@ -309,6 +432,34 @@ describe('group', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it(`should add group to user's groups array`, async () => {
|
||||
const dbGroup = await groupController.createGroup(group)
|
||||
const dbUser = await userController.createUser({
|
||||
...user,
|
||||
username: 'addUserToGroup'
|
||||
})
|
||||
|
||||
await request(app)
|
||||
.post(`/SASjsApi/group/${dbGroup.groupId}/${dbUser.id}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
const res = await request(app)
|
||||
.get(`/SASjsApi/user/${dbUser.id}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
expect(res.body.groups).toEqual([
|
||||
{
|
||||
groupId: expect.anything(),
|
||||
name: group.name,
|
||||
description: group.description
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('should respond with group without duplicating user', async () => {
|
||||
const dbGroup = await groupController.createGroup(group)
|
||||
const dbUser = await userController.createUser({
|
||||
@@ -362,26 +513,26 @@ describe('group', () => {
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Forbidden if groupId is incorrect', async () => {
|
||||
it('should respond with Not Found if groupId is incorrect', async () => {
|
||||
const res = await request(app)
|
||||
.post('/SASjsApi/group/123/123')
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(403)
|
||||
.expect(404)
|
||||
|
||||
expect(res.text).toEqual('Error: Group not found.')
|
||||
expect(res.text).toEqual('Group not found.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Forbidden if userId is incorrect', async () => {
|
||||
it('should respond with Not Found if userId is incorrect', async () => {
|
||||
const dbGroup = await groupController.createGroup(group)
|
||||
const res = await request(app)
|
||||
.post(`/SASjsApi/group/${dbGroup.groupId}/123`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(403)
|
||||
.expect(404)
|
||||
|
||||
expect(res.text).toEqual('Error: User not found.')
|
||||
expect(res.text).toEqual('User not found.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
})
|
||||
@@ -412,6 +563,29 @@ describe('group', () => {
|
||||
expect(res.body.users).toEqual([])
|
||||
})
|
||||
|
||||
it(`should remove group from user's groups array`, async () => {
|
||||
const dbGroup = await groupController.createGroup(group)
|
||||
const dbUser = await userController.createUser({
|
||||
...user,
|
||||
username: 'removeGroupFromUser'
|
||||
})
|
||||
await groupController.addUserToGroup(dbGroup.groupId, dbUser.id)
|
||||
|
||||
await request(app)
|
||||
.delete(`/SASjsApi/group/${dbGroup.groupId}/${dbUser.id}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
const res = await request(app)
|
||||
.get(`/SASjsApi/user/${dbUser.id}`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(200)
|
||||
|
||||
expect(res.body.groups).toEqual([])
|
||||
})
|
||||
|
||||
it('should respond with Unauthorized if access token is not present', async () => {
|
||||
const res = await request(app)
|
||||
.delete('/SASjsApi/group/123/123')
|
||||
@@ -438,26 +612,26 @@ describe('group', () => {
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Forbidden if groupId is incorrect', async () => {
|
||||
it('should respond with Not Found if groupId is incorrect', async () => {
|
||||
const res = await request(app)
|
||||
.delete('/SASjsApi/group/123/123')
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(403)
|
||||
.expect(404)
|
||||
|
||||
expect(res.text).toEqual('Error: Group not found.')
|
||||
expect(res.text).toEqual('Group not found.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
|
||||
it('should respond with Forbidden if userId is incorrect', async () => {
|
||||
it('should respond with Not Found if userId is incorrect', async () => {
|
||||
const dbGroup = await groupController.createGroup(group)
|
||||
const res = await request(app)
|
||||
.delete(`/SASjsApi/group/${dbGroup.groupId}/123`)
|
||||
.auth(adminAccessToken, { type: 'bearer' })
|
||||
.send()
|
||||
.expect(403)
|
||||
.expect(404)
|
||||
|
||||
expect(res.text).toEqual('Error: User not found.')
|
||||
expect(res.text).toEqual('User not found.')
|
||||
expect(res.body).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -23,13 +23,21 @@ export const appStreamHtml = (appStreamConfig: AppStreamConfig) => `
|
||||
${style}
|
||||
</head>
|
||||
<body>
|
||||
<h1>App Stream</h1>
|
||||
<header>
|
||||
<a href="/"><img src="/logo.png" alt="logo" class="logo"></a>
|
||||
<h1>App Stream</h1>
|
||||
</header>
|
||||
<div class="app-container">
|
||||
${Object.entries(appStreamConfig)
|
||||
.map(([streamServiceName, entry]) =>
|
||||
singleAppStreamHtml(streamServiceName, entry.appLoc, entry.streamLogo)
|
||||
)
|
||||
.join('')}
|
||||
${Object.entries(appStreamConfig)
|
||||
.map(([streamServiceName, entry]) =>
|
||||
singleAppStreamHtml(
|
||||
streamServiceName,
|
||||
entry.appLoc,
|
||||
entry.streamLogo
|
||||
)
|
||||
)
|
||||
.join('')}
|
||||
|
||||
<a class="app" title="Upload build.json">
|
||||
<input id="fileId" type="file" hidden />
|
||||
<button id="uploadButton" style="margin-bottom: 5px; cursor: pointer">
|
||||
|
||||
@@ -5,18 +5,71 @@ export const style = `<style>
|
||||
.app-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 50px;
|
||||
}
|
||||
.app-container .app {
|
||||
width: 150px;
|
||||
height: 180px;
|
||||
margin: 10px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
|
||||
background: #efefef;
|
||||
padding: 10px;
|
||||
border-radius: 7px;
|
||||
border: 1px solid #d7d7d7;
|
||||
}
|
||||
.app-container .app img{
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
#uploadButton {
|
||||
border: 0
|
||||
}
|
||||
|
||||
#uploadButton:focus {
|
||||
outline: 0
|
||||
}
|
||||
|
||||
#uploadMessage {
|
||||
position: relative;
|
||||
bottom: -5px;
|
||||
}
|
||||
|
||||
header {
|
||||
transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
box-shadow: rgb(0 0 0 / 20%) 0px 2px 4px -1px, rgb(0 0 0 / 14%) 0px 4px 5px 0px, rgb(0 0 0 / 12%) 0px 1px 10px 0px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: auto;
|
||||
right: 0px;
|
||||
background-color: rgb(0, 0, 0);
|
||||
color: rgb(255, 255, 255);
|
||||
z-index: 1201;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
margin: 13px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
header a {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
header .logo {
|
||||
width: 35px;
|
||||
margin-left: 10px;
|
||||
align-self: center;
|
||||
}
|
||||
</style>`
|
||||
|
||||
6
api/src/utils/extractName.ts
Normal file
6
api/src/utils/extractName.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import path from 'path'
|
||||
|
||||
export const extractName = (filePath: string) => {
|
||||
const extension = path.extname(filePath)
|
||||
return path.basename(filePath, extension)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import path from 'path'
|
||||
import { homedir } from 'os'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
export const apiRoot = path.join(__dirname, '..', '..')
|
||||
export const codebaseRoot = path.join(apiRoot, '..')
|
||||
@@ -47,3 +48,6 @@ export const generateUniqueFileName = (fileName: string, extension = '') =>
|
||||
new Date().getTime(),
|
||||
extension
|
||||
].join('')
|
||||
|
||||
export const createReadStream = async (filePath: string) =>
|
||||
fs.createReadStream(filePath)
|
||||
|
||||
@@ -3,6 +3,7 @@ export * from './connectDB'
|
||||
export * from './copySASjsCore'
|
||||
export * from './desktopAutoExec'
|
||||
export * from './extractHeaders'
|
||||
export * from './extractName'
|
||||
export * from './file'
|
||||
export * from './generateAccessToken'
|
||||
export * from './generateAuthCode'
|
||||
@@ -13,6 +14,7 @@ export * from './getPreProgramVariables'
|
||||
export * from './getServerUrl'
|
||||
export * from './instantiateLogger'
|
||||
export * from './isDebugOn'
|
||||
export * from './zipped'
|
||||
export * from './parseLogToArray'
|
||||
export * from './removeTokensInDB'
|
||||
export * from './saveTokensInDB'
|
||||
|
||||
@@ -2,6 +2,7 @@ import Joi from 'joi'
|
||||
|
||||
const usernameSchema = Joi.string().lowercase().alphanum().min(3).max(16)
|
||||
const passwordSchema = Joi.string().min(6).max(1024)
|
||||
const groupnameSchema = Joi.string().lowercase().alphanum().min(3).max(16)
|
||||
|
||||
export const blockFileRegex = /\.(exe|sh|htaccess)$/i
|
||||
|
||||
@@ -29,11 +30,16 @@ export const tokenValidation = (data: any): Joi.ValidationResult =>
|
||||
|
||||
export const registerGroupValidation = (data: any): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
name: Joi.string().min(6).required(),
|
||||
name: groupnameSchema.required(),
|
||||
description: Joi.string(),
|
||||
isActive: Joi.boolean()
|
||||
}).validate(data)
|
||||
|
||||
export const getGroupValidation = (data: any): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
name: groupnameSchema.required()
|
||||
}).validate(data)
|
||||
|
||||
export const registerUserValidation = (data: any): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
displayName: Joi.string().min(6).required(),
|
||||
|
||||
40
api/src/utils/zipped.ts
Normal file
40
api/src/utils/zipped.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import path from 'path'
|
||||
import unZipper from 'unzipper'
|
||||
import { extractName } from './extractName'
|
||||
import { createReadStream } from './file'
|
||||
|
||||
export const isZipFile = (
|
||||
file: Express.Multer.File
|
||||
): { error?: string; value?: Express.Multer.File } => {
|
||||
const fileExtension = path.extname(file.originalname)
|
||||
if (fileExtension.toUpperCase() !== '.ZIP')
|
||||
return { error: `"file" has invalid extension ${fileExtension}` }
|
||||
|
||||
const allowedMimetypes = ['application/zip', 'application/x-zip-compressed']
|
||||
|
||||
if (!allowedMimetypes.includes(file.mimetype))
|
||||
return { error: `"file" has invalid type ${file.mimetype}` }
|
||||
|
||||
return { value: file }
|
||||
}
|
||||
|
||||
export const extractJSONFromZip = async (zipFile: Express.Multer.File) => {
|
||||
let fileContent: string = ''
|
||||
|
||||
const fileInZip = extractName(zipFile.originalname)
|
||||
const zip = (await createReadStream(zipFile.path)).pipe(
|
||||
unZipper.Parse({ forceStream: true })
|
||||
)
|
||||
|
||||
for await (const entry of zip) {
|
||||
const fileName = entry.path as string
|
||||
if (fileName.toUpperCase().endsWith('.JSON') && fileName === fileInZip) {
|
||||
fileContent = await entry.buffer()
|
||||
break
|
||||
} else {
|
||||
entry.autodrain()
|
||||
}
|
||||
}
|
||||
|
||||
return fileContent
|
||||
}
|
||||
122
package-lock.json
generated
122
package-lock.json
generated
@@ -2770,9 +2770,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-8.10.0.tgz",
|
||||
"integrity": "sha512-6oo65q9Quv9mRPGZJufmSH+C/UFdgelwzRXiglT/2mDB50zdy/lZK5dFY0TJ9fJ/8gHqnxcX1NM206KLjTBMlQ==",
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-8.12.2.tgz",
|
||||
"integrity": "sha512-TArexqro9wpl/6wz6t6YdYhOoiy/UArqiSsSsqI7fieEhQEswDQSJcgt/LuCDjl6mfCDi0So7S2UZ979qLYRPg==",
|
||||
"bundleDependencies": [
|
||||
"@isaacs/string-locale-compare",
|
||||
"@npmcli/arborist",
|
||||
@@ -2858,7 +2858,7 @@
|
||||
"@npmcli/run-script": "^3.0.1",
|
||||
"abbrev": "~1.1.1",
|
||||
"archy": "~1.0.0",
|
||||
"cacache": "^16.0.7",
|
||||
"cacache": "^16.1.1",
|
||||
"chalk": "^4.1.2",
|
||||
"chownr": "^2.0.0",
|
||||
"cli-columns": "^4.0.0",
|
||||
@@ -2883,7 +2883,7 @@
|
||||
"libnpmsearch": "^5.0.2",
|
||||
"libnpmteam": "^4.0.2",
|
||||
"libnpmversion": "^3.0.1",
|
||||
"make-fetch-happen": "^10.1.3",
|
||||
"make-fetch-happen": "^10.1.7",
|
||||
"minipass": "^3.1.6",
|
||||
"minipass-pipeline": "^1.2.4",
|
||||
"mkdirp": "^1.0.4",
|
||||
@@ -2900,7 +2900,7 @@
|
||||
"npm-user-validate": "^1.0.1",
|
||||
"npmlog": "^6.0.2",
|
||||
"opener": "^1.5.2",
|
||||
"pacote": "^13.3.0",
|
||||
"pacote": "^13.6.0",
|
||||
"parse-conflict-json": "^2.0.2",
|
||||
"proc-log": "^2.0.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
@@ -2910,7 +2910,7 @@
|
||||
"readdir-scoped-modules": "^1.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.7",
|
||||
"ssri": "^9.0.0",
|
||||
"ssri": "^9.0.1",
|
||||
"tar": "^6.1.11",
|
||||
"text-table": "~0.2.0",
|
||||
"tiny-relative-date": "^1.3.0",
|
||||
@@ -2965,7 +2965,7 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/npm/node_modules/@npmcli/arborist": {
|
||||
"version": "5.2.0",
|
||||
"version": "5.2.1",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -3389,7 +3389,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/cacache": {
|
||||
"version": "16.0.7",
|
||||
"version": "16.1.1",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -3759,7 +3759,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/glob": {
|
||||
"version": "8.0.1",
|
||||
"version": "8.0.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -3769,8 +3769,7 @@
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
"once": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -4121,7 +4120,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/libnpmexec": {
|
||||
"version": "4.0.5",
|
||||
"version": "4.0.6",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4186,7 +4185,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/libnpmpack": {
|
||||
"version": "4.0.3",
|
||||
"version": "4.1.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4194,7 +4193,7 @@
|
||||
"dependencies": {
|
||||
"@npmcli/run-script": "^3.0.0",
|
||||
"npm-package-arg": "^9.0.1",
|
||||
"pacote": "^13.0.5"
|
||||
"pacote": "^13.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||
@@ -4272,14 +4271,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/make-fetch-happen": {
|
||||
"version": "10.1.3",
|
||||
"version": "10.1.7",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"agentkeepalive": "^4.2.1",
|
||||
"cacache": "^16.0.2",
|
||||
"cacache": "^16.1.0",
|
||||
"http-cache-semantics": "^4.1.0",
|
||||
"http-proxy-agent": "^5.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
@@ -4292,7 +4291,7 @@
|
||||
"minipass-pipeline": "^1.2.4",
|
||||
"negotiator": "^0.6.3",
|
||||
"promise-retry": "^2.0.1",
|
||||
"socks-proxy-agent": "^6.1.1",
|
||||
"socks-proxy-agent": "^7.0.0",
|
||||
"ssri": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4300,7 +4299,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/minimatch": {
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4509,7 +4508,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/node-gyp/node_modules/glob": {
|
||||
"version": "7.2.0",
|
||||
"version": "7.2.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4518,7 +4517,7 @@
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
@@ -4633,7 +4632,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/npm-packlist": {
|
||||
"version": "5.0.3",
|
||||
"version": "5.1.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4760,7 +4759,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/pacote": {
|
||||
"version": "13.3.0",
|
||||
"version": "13.6.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4777,7 +4776,7 @@
|
||||
"minipass": "^3.1.6",
|
||||
"mkdirp": "^1.0.4",
|
||||
"npm-package-arg": "^9.0.0",
|
||||
"npm-packlist": "^5.0.0",
|
||||
"npm-packlist": "^5.1.0",
|
||||
"npm-pick-manifest": "^7.0.0",
|
||||
"npm-registry-fetch": "^13.0.1",
|
||||
"proc-log": "^2.0.0",
|
||||
@@ -5009,7 +5008,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/rimraf/node_modules/glob": {
|
||||
"version": "7.2.0",
|
||||
"version": "7.2.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -5018,7 +5017,7 @@
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
@@ -5141,7 +5140,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/socks-proxy-agent": {
|
||||
"version": "6.2.0",
|
||||
"version": "7.0.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
@@ -5192,7 +5191,7 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/npm/node_modules/ssri": {
|
||||
"version": "9.0.0",
|
||||
"version": "9.0.1",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -5911,9 +5910,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/semantic-release": {
|
||||
"version": "19.0.2",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.2.tgz",
|
||||
"integrity": "sha512-7tPonjZxukKECmClhsfyMKDt0GR38feIC2HxgyYaBi+9tDySBLjK/zYDLhh+m6yjnHIJa9eBTKYE7k63ZQcYbw==",
|
||||
"version": "19.0.3",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.3.tgz",
|
||||
"integrity": "sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
@@ -9019,9 +9018,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"npm": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-8.10.0.tgz",
|
||||
"integrity": "sha512-6oo65q9Quv9mRPGZJufmSH+C/UFdgelwzRXiglT/2mDB50zdy/lZK5dFY0TJ9fJ/8gHqnxcX1NM206KLjTBMlQ==",
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-8.12.2.tgz",
|
||||
"integrity": "sha512-TArexqro9wpl/6wz6t6YdYhOoiy/UArqiSsSsqI7fieEhQEswDQSJcgt/LuCDjl6mfCDi0So7S2UZ979qLYRPg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
@@ -9035,7 +9034,7 @@
|
||||
"@npmcli/run-script": "^3.0.1",
|
||||
"abbrev": "~1.1.1",
|
||||
"archy": "~1.0.0",
|
||||
"cacache": "^16.0.7",
|
||||
"cacache": "^16.1.1",
|
||||
"chalk": "^4.1.2",
|
||||
"chownr": "^2.0.0",
|
||||
"cli-columns": "^4.0.0",
|
||||
@@ -9060,7 +9059,7 @@
|
||||
"libnpmsearch": "^5.0.2",
|
||||
"libnpmteam": "^4.0.2",
|
||||
"libnpmversion": "^3.0.1",
|
||||
"make-fetch-happen": "^10.1.3",
|
||||
"make-fetch-happen": "^10.1.7",
|
||||
"minipass": "^3.1.6",
|
||||
"minipass-pipeline": "^1.2.4",
|
||||
"mkdirp": "^1.0.4",
|
||||
@@ -9077,7 +9076,7 @@
|
||||
"npm-user-validate": "^1.0.1",
|
||||
"npmlog": "^6.0.2",
|
||||
"opener": "^1.5.2",
|
||||
"pacote": "^13.3.0",
|
||||
"pacote": "^13.6.0",
|
||||
"parse-conflict-json": "^2.0.2",
|
||||
"proc-log": "^2.0.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
@@ -9087,7 +9086,7 @@
|
||||
"readdir-scoped-modules": "^1.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.7",
|
||||
"ssri": "^9.0.0",
|
||||
"ssri": "^9.0.1",
|
||||
"tar": "^6.1.11",
|
||||
"text-table": "~0.2.0",
|
||||
"tiny-relative-date": "^1.3.0",
|
||||
@@ -9117,7 +9116,7 @@
|
||||
"peer": true
|
||||
},
|
||||
"@npmcli/arborist": {
|
||||
"version": "5.2.0",
|
||||
"version": "5.2.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -9432,7 +9431,7 @@
|
||||
}
|
||||
},
|
||||
"cacache": {
|
||||
"version": "16.0.7",
|
||||
"version": "16.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -9704,7 +9703,7 @@
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "8.0.1",
|
||||
"version": "8.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -9713,8 +9712,7 @@
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
"once": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
@@ -9970,7 +9968,7 @@
|
||||
}
|
||||
},
|
||||
"libnpmexec": {
|
||||
"version": "4.0.5",
|
||||
"version": "4.0.6",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -10019,14 +10017,14 @@
|
||||
}
|
||||
},
|
||||
"libnpmpack": {
|
||||
"version": "4.0.3",
|
||||
"version": "4.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@npmcli/run-script": "^3.0.0",
|
||||
"npm-package-arg": "^9.0.1",
|
||||
"pacote": "^13.0.5"
|
||||
"pacote": "^13.5.0"
|
||||
}
|
||||
},
|
||||
"libnpmpublish": {
|
||||
@@ -10081,13 +10079,13 @@
|
||||
"peer": true
|
||||
},
|
||||
"make-fetch-happen": {
|
||||
"version": "10.1.3",
|
||||
"version": "10.1.7",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"agentkeepalive": "^4.2.1",
|
||||
"cacache": "^16.0.2",
|
||||
"cacache": "^16.1.0",
|
||||
"http-cache-semantics": "^4.1.0",
|
||||
"http-proxy-agent": "^5.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
@@ -10100,12 +10098,12 @@
|
||||
"minipass-pipeline": "^1.2.4",
|
||||
"negotiator": "^0.6.3",
|
||||
"promise-retry": "^2.0.1",
|
||||
"socks-proxy-agent": "^6.1.1",
|
||||
"socks-proxy-agent": "^7.0.0",
|
||||
"ssri": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "5.0.1",
|
||||
"version": "5.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -10254,7 +10252,7 @@
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.0",
|
||||
"version": "7.2.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -10262,7 +10260,7 @@
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
@@ -10344,7 +10342,7 @@
|
||||
}
|
||||
},
|
||||
"npm-packlist": {
|
||||
"version": "5.0.3",
|
||||
"version": "5.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -10435,7 +10433,7 @@
|
||||
}
|
||||
},
|
||||
"pacote": {
|
||||
"version": "13.3.0",
|
||||
"version": "13.6.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -10451,7 +10449,7 @@
|
||||
"minipass": "^3.1.6",
|
||||
"mkdirp": "^1.0.4",
|
||||
"npm-package-arg": "^9.0.0",
|
||||
"npm-packlist": "^5.0.0",
|
||||
"npm-packlist": "^5.1.0",
|
||||
"npm-pick-manifest": "^7.0.0",
|
||||
"npm-registry-fetch": "^13.0.1",
|
||||
"proc-log": "^2.0.0",
|
||||
@@ -10615,7 +10613,7 @@
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.0",
|
||||
"version": "7.2.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -10623,7 +10621,7 @@
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
@@ -10701,7 +10699,7 @@
|
||||
}
|
||||
},
|
||||
"socks-proxy-agent": {
|
||||
"version": "6.2.0",
|
||||
"version": "7.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -10744,7 +10742,7 @@
|
||||
"peer": true
|
||||
},
|
||||
"ssri": {
|
||||
"version": "9.0.0",
|
||||
"version": "9.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
@@ -11270,9 +11268,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"semantic-release": {
|
||||
"version": "19.0.2",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.2.tgz",
|
||||
"integrity": "sha512-7tPonjZxukKECmClhsfyMKDt0GR38feIC2HxgyYaBi+9tDySBLjK/zYDLhh+m6yjnHIJa9eBTKYE7k63ZQcYbw==",
|
||||
"version": "19.0.3",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.3.tgz",
|
||||
"integrity": "sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
|
||||
Reference in New Issue
Block a user