From 7d26edfea69435dbfe74d823103484e60d6175d9 Mon Sep 17 00:00:00 2001 From: Viachaslau Date: Mon, 15 Jul 2024 15:00:32 +0400 Subject: [PATCH] feat(misc): function scan examples (#78) --- package-lock.json | 645 +++++++++++++++++++------ package.json | 17 +- src/app.module.ts | 2 + src/main.ts | 10 +- src/misc/index.ts | 1 + src/misc/misc.controller.spec.ts | 108 +++++ src/misc/misc.controller.ts | 105 ++++ src/misc/misc.module.ts | 10 + src/misc/services/date.service.spec.ts | 79 +++ src/misc/services/date.service.ts | 28 ++ src/misc/services/file.service.spec.ts | 72 +++ src/misc/services/file.service.ts | 13 + src/misc/services/index.ts | 3 + src/misc/services/xml.service.spec.ts | 36 ++ src/misc/services/xml.service.ts | 44 ++ test/sec/fn-date.e2e-spec.ts | 53 ++ test/sec/fn-file.e2e-spec.ts | 50 ++ test/sec/fn-xml.e2e-spec.ts | 45 ++ 18 files changed, 1176 insertions(+), 145 deletions(-) create mode 100644 src/misc/index.ts create mode 100644 src/misc/misc.controller.spec.ts create mode 100644 src/misc/misc.controller.ts create mode 100644 src/misc/misc.module.ts create mode 100644 src/misc/services/date.service.spec.ts create mode 100644 src/misc/services/date.service.ts create mode 100644 src/misc/services/file.service.spec.ts create mode 100644 src/misc/services/file.service.ts create mode 100644 src/misc/services/index.ts create mode 100644 src/misc/services/xml.service.spec.ts create mode 100644 src/misc/services/xml.service.ts create mode 100644 test/sec/fn-date.e2e-spec.ts create mode 100644 test/sec/fn-file.e2e-spec.ts create mode 100644 test/sec/fn-xml.e2e-spec.ts diff --git a/package-lock.json b/package-lock.json index 1b4aa61..61db7a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,8 @@ "@nestjs/swagger": "^7.4.0", "dotenv": "^16.4.5", "swagger-ui-express": "^5.0.1", - "tslib": "~2.6.3" + "tslib": "~2.6.3", + "xml2js": "^0.6.2" }, "devDependencies": { "@commitlint/cli": "^19.3.0", @@ -29,17 +30,17 @@ "@nestjs/cli": "^10.4.2", "@nestjs/schematics": "^10.1.2", "@nestjs/testing": "^10.3.10", - "@sectester/core": "^0.32.0", - "@sectester/repeater": "^0.32.0", - "@sectester/reporter": "^0.32.0", - "@sectester/runner": "^0.32.0", - "@sectester/scan": "^0.32.0", + "@sectester/core": "^0.33.1", + "@sectester/repeater": "^0.33.1", + "@sectester/reporter": "^0.33.1", + "@sectester/runner": "^0.33.1", + "@sectester/scan": "^0.33.1", "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", - "@types/express": "^4.17.21", "@types/jest": "^29.5.12", "@types/node": "^18.19.39", "@types/supertest": "^6.0.2", + "@types/xml2js": "^0.4.14", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "detect-port": "^1.6.1", @@ -1239,6 +1240,45 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fastify/ajv-compiler": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.6.0.tgz", + "integrity": "sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "fast-uri": "^2.0.0" + } + }, + "node_modules/@fastify/error": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", + "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", + "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stringify": "^5.7.0" + } + }, + "node_modules/@fastify/merge-json-schemas": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", + "integrity": "sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, "node_modules/@har-sdk/core": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/@har-sdk/core/-/core-1.4.5.tgz", @@ -3294,9 +3334,9 @@ "license": "BSD-3-Clause" }, "node_modules/@sectester/core": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@sectester/core/-/core-0.32.0.tgz", - "integrity": "sha512-cfNmrPr8cf7JxBt/fp/neEtv139EkrpShZYyuiQ4ESCL9n6xViPgabIlDbLjRmsRgoSL2JnTrmRJuytDPtoH8w==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/@sectester/core/-/core-0.33.1.tgz", + "integrity": "sha512-eWpPrFyfz6XndOmRHYiBAVsHO0QVzzA3UMlegjgD9VbEr3uJR5SmqZBUhlIj8r09+6/maFYj0I10x63sWTRWog==", "dev": true, "license": "MIT", "dependencies": { @@ -3368,9 +3408,9 @@ "license": "MIT" }, "node_modules/@sectester/repeater": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@sectester/repeater/-/repeater-0.32.0.tgz", - "integrity": "sha512-76f8F7bDfl96fk39tBAGytfCnifmXbz5RMHeJPlYetsJ7gdOmjkDdgKwdnTt7QO/rK6UaazQ/DwMMCxVQWAcLw==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/@sectester/repeater/-/repeater-0.33.1.tgz", + "integrity": "sha512-6XumXKovgxWyZPG4zsApNsjCgGwiGQ6Fqu8KBKbxW27FlLSYBK/VZw55FuwIoiI8AJZYvaQB86E7cPSQJLkD1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3382,7 +3422,7 @@ "reflect-metadata": "^0.2.2", "socket.io-client": "^4.7.5", "socket.io-msgpack-parser": "^3.0.2", - "socks-proxy-agent": "^6.2.1", + "socks-proxy-agent": "^8.0.4", "tslib": "~2.6.3", "tsyringe": "^4.8.0", "uuid": "^10.0.0" @@ -3449,9 +3489,9 @@ "license": "MIT" }, "node_modules/@sectester/reporter": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@sectester/reporter/-/reporter-0.32.0.tgz", - "integrity": "sha512-bMkJngeF8R5UPkDwlQLwBZTmLBHCW08nM+2SGftHIeBjrTUwA5m25ZL1cSRYY3r6GZKBz0DouVDzAqsA0Rk/uw==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/@sectester/reporter/-/reporter-0.33.1.tgz", + "integrity": "sha512-4lmblDtABT43JN6l2Zq8iFQ3ZlRTmmwLjZTWLU/SU7Y77nMkIgrN4gpTIvdAavw/FZMJfpFDwiMR1zFk8J8cpg==", "dev": true, "license": "MIT", "dependencies": { @@ -3521,12 +3561,13 @@ "license": "MIT" }, "node_modules/@sectester/runner": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@sectester/runner/-/runner-0.32.0.tgz", - "integrity": "sha512-65l4fIX7kDqOaWrwBVQGQiFTqxkJL7FEhpXhnbV8k1gzlCk9lzm6IDEUjYDODQxSPQ0sE61GRCmPH3BC94Aw0A==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/@sectester/runner/-/runner-0.33.1.tgz", + "integrity": "sha512-J2RoZpsLnyyxjiAGZ3bsku57VuTakp5CqoL+XRiyOBvCs8K4Vblc6hFqwjqjXc7HfJ1XXxByWEeZe/5zzemvcw==", "dev": true, "license": "MIT", "dependencies": { + "fastify": "~4.15.0", "tslib": "~2.6.3" }, "engines": { @@ -3541,9 +3582,9 @@ } }, "node_modules/@sectester/scan": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@sectester/scan/-/scan-0.32.0.tgz", - "integrity": "sha512-n60BNd0settD8zL8V91Pa+XzLTq575oleqgRlVjwsJR4EyR4lMaMKjin2CZWxRyZmCX7bJYvu6unhuFC6CcC6Q==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/@sectester/scan/-/scan-0.33.1.tgz", + "integrity": "sha512-nJKbHGmqFyH2Og/Z9wwxXLam2dRlwDUyG6Ezpgf+Jp5TjZn1u908Tr0W9jQMQhXxymRL9jJ6lgUOziylBn/hEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4291,27 +4332,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/conventional-commits-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", @@ -4358,32 +4378,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -4394,13 +4388,6 @@ "@types/node": "*" } }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -4460,13 +4447,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "18.19.39", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", @@ -4484,43 +4464,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -4551,6 +4494,16 @@ "@types/superagent": "^8.1.0" } }, + "node_modules/@types/xml2js": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz", + "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -4943,6 +4896,26 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", + "dev": true, + "license": "MIT" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -5380,6 +5353,16 @@ "dev": true, "license": "MIT" }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -5396,6 +5379,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/avvio": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.3.2.tgz", + "integrity": "sha512-st8e519GWHa/azv8S87mcJvZs4WsgTBjOw/Ih1CP6u+8SZvcOeAYNG6JbsIrAUUJJ7JfmrnOkR8ipDS+u9SIRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/error": "^3.3.0", + "fastq": "^1.17.1" + } + }, "node_modules/axios": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", @@ -8022,6 +8016,16 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -8187,6 +8191,13 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8216,6 +8227,40 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-json-stringify": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.16.1.tgz", + "integrity": "sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/merge-json-schemas": "^0.1.0", + "ajv": "^8.10.0", + "ajv-formats": "^3.0.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^2.1.0", + "json-schema-ref-resolver": "^1.0.1", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -8223,12 +8268,63 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "license": "MIT" }, + "node_modules/fast-uri": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", + "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastify": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.15.0.tgz", + "integrity": "sha512-m/CaRN8nf5uyYdrDe2qqq+0z3oGyE+A++qlKQoLJTI4WI0nWK9D6R3FxXQ3MVwt/md977GMR4F43pE9oqrS2zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/ajv-compiler": "^3.5.0", + "@fastify/error": "^3.0.0", + "@fastify/fast-json-stringify-compiler": "^4.2.0", + "abstract-logging": "^2.0.1", + "avvio": "^8.2.0", + "fast-content-type-parse": "^1.0.0", + "find-my-way": "^7.6.0", + "light-my-request": "^5.6.1", + "pino": "^8.5.0", + "process-warning": "^2.0.0", + "proxy-addr": "^2.0.7", + "rfdc": "^1.3.0", + "secure-json-parse": "^2.5.0", + "semver": "^7.3.7", + "tiny-lru": "^10.0.0" + } + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -8368,6 +8464,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/find-my-way": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-7.7.0.tgz", + "integrity": "sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/find-up": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", @@ -11970,6 +12081,16 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema-ref-resolver": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", + "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -12170,6 +12291,25 @@ "node": ">= 0.8.0" } }, + "node_modules/light-my-request": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.13.0.tgz", + "integrity": "sha512-9IjUN9ZyCS9pTG+KqTDEQo68Sui2lHsYBrfMyVUTTZ3XhH8PMZq7xO94Kr+eP9dhi/kcKsx4N41p2IXEBil1pQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "cookie": "^0.6.0", + "process-warning": "^3.0.0", + "set-cookie-parser": "^2.4.1" + } + }, + "node_modules/light-my-request/node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lilconfig": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", @@ -15976,6 +16116,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -16559,6 +16709,106 @@ "node": ">=4" } }, + "node_modules/pino": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz", + "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.6.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/pino/node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true, + "license": "MIT" + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -16841,12 +17091,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "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==", "license": "MIT" }, + "node_modules/process-warning": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.2.tgz", + "integrity": "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==", + "dev": true, + "license": "MIT" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -16949,6 +17216,13 @@ ], "license": "MIT" }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "dev": true, + "license": "MIT" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -17165,6 +17439,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -17367,6 +17651,16 @@ "dev": true, "license": "ISC" }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -17509,12 +17803,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-regex2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", + "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ret": "~0.2.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -17568,6 +17888,13 @@ "dev": true, "license": "MIT" }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/semantic-release": { "version": "22.0.12", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-22.0.12.tgz", @@ -17894,6 +18221,13 @@ "dev": true, "license": "ISC" }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true, + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -18346,31 +18680,28 @@ } }, "node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 10" + "node": ">= 14" } }, - "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/sonic-boom": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" + "atomic-sleep": "^1.0.0" } }, "node_modules/source-map": { @@ -19109,6 +19440,16 @@ "dev": true, "license": "MIT" }, + "node_modules/thread-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -19136,6 +19477,16 @@ "node": ">=8" } }, + "node_modules/tiny-lru": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-10.4.1.tgz", + "integrity": "sha512-buLIzw7ppqymuO3pt10jHk/6QMeZLbidihMQU+N6sogF6EnBzG0qtDWIHuhw1x3dyNgVL/KTGIZsTK81+yCzLg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -20309,6 +20660,28 @@ } } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", diff --git a/package.json b/package.json index 1a3a4dc..eb95b58 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --report-unused-disable-directives --fix", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", @@ -71,7 +71,8 @@ "@nestjs/swagger": "^7.4.0", "dotenv": "^16.4.5", "swagger-ui-express": "^5.0.1", - "tslib": "~2.6.3" + "tslib": "~2.6.3", + "xml2js": "^0.6.2" }, "devDependencies": { "@commitlint/cli": "^19.3.0", @@ -80,17 +81,17 @@ "@nestjs/cli": "^10.4.2", "@nestjs/schematics": "^10.1.2", "@nestjs/testing": "^10.3.10", - "@sectester/core": "^0.32.0", - "@sectester/repeater": "^0.32.0", - "@sectester/reporter": "^0.32.0", - "@sectester/runner": "^0.32.0", - "@sectester/scan": "^0.32.0", + "@sectester/core": "^0.33.1", + "@sectester/repeater": "^0.33.1", + "@sectester/reporter": "^0.33.1", + "@sectester/runner": "^0.33.1", + "@sectester/scan": "^0.33.1", "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", - "@types/express": "^4.17.21", "@types/jest": "^29.5.12", "@types/node": "^18.19.39", "@types/supertest": "^6.0.2", + "@types/xml2js": "^0.4.14", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "detect-port": "^1.6.1", diff --git a/src/app.module.ts b/src/app.module.ts index 131e3b4..d0fb010 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,5 +1,6 @@ import { UsersModule } from './users'; import { MikroOrmConfigFactory } from './config'; +import { MiscModule } from './misc'; import { Module } from '@nestjs/common'; import { MikroOrmModule } from '@mikro-orm/nestjs'; import { ConfigModule } from '@nestjs/config'; @@ -7,6 +8,7 @@ import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ UsersModule, + MiscModule, ConfigModule.forRoot(), MikroOrmModule.forRootAsync({ useClass: MikroOrmConfigFactory diff --git a/src/main.ts b/src/main.ts index 8030a3c..07a4d9a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,12 +2,20 @@ import { AppModule } from './app.module'; import { NestFactory } from '@nestjs/core'; import { logger } from '@mikro-orm/nestjs'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; +import { NestExpressApplication } from '@nestjs/platform-express'; const bootstrap = async () => { - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create(AppModule, { + rawBody: true + }); app.enableShutdownHooks(); + app.useBodyParser('text', { + type: ['text/xml', 'application/xml'], + limit: '1mb' + }); + const config = new DocumentBuilder() .setTitle('SecTester JS Demo') .setDescription( diff --git a/src/misc/index.ts b/src/misc/index.ts new file mode 100644 index 0000000..b5ee52e --- /dev/null +++ b/src/misc/index.ts @@ -0,0 +1 @@ +export { MiscModule } from './misc.module'; diff --git a/src/misc/misc.controller.spec.ts b/src/misc/misc.controller.spec.ts new file mode 100644 index 0000000..43a3447 --- /dev/null +++ b/src/misc/misc.controller.spec.ts @@ -0,0 +1,108 @@ +import { MiscController } from './misc.controller'; +import { DateService, FileService, XmlService } from './services'; +import { Test, TestingModule } from '@nestjs/testing'; +import { RawBodyRequest } from '@nestjs/common'; +import { IncomingMessage } from 'http'; + +describe('MiscController', () => { + let miscController: MiscController; + let dateService: jest.Mocked; + let fileService: jest.Mocked; + let xmlService: jest.Mocked; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [MiscController], + providers: [ + { + provide: DateService, + useValue: { + calculateWeekdays: jest.fn() + } + }, + { + provide: FileService, + useValue: { + fetch: jest.fn() + } + }, + { + provide: XmlService, + useValue: { + parse: jest.fn() + } + } + ] + }).compile(); + + miscController = module.get(MiscController); + dateService = module.get(DateService); + fileService = module.get(FileService); + xmlService = module.get(XmlService); + }); + + it('should be defined', () => expect(miscController).toBeDefined()); + + describe('fetch', () => { + it('should call fileService fetch() with the provided URL', async () => { + const url = 'https://example.com'; + const expectedResult = 'fetched content'; + fileService.fetch.mockResolvedValue(expectedResult); + + const result = await miscController.fetch({ url }); + + expect(fileService.fetch).toHaveBeenCalledWith(url); + expect(result).toBe(expectedResult); + }); + }); + + describe('parse', () => { + it('should call xmlService parse() with the request body', async () => { + const xmlBody = 'content'; + const expectedResult = 'parsed content'; + xmlService.parse.mockResolvedValue(expectedResult); + const mockRequest = { + rawBody: Buffer.from(xmlBody) + } as RawBodyRequest; + + const result = await miscController.parse(mockRequest); + + expect(xmlService.parse).toHaveBeenCalledWith(xmlBody); + expect(result).toBe(expectedResult); + }); + }); + + describe('weekdays', () => { + it('should call dateService calculateWeekdays() and return JSON result', async () => { + const from = '2023-01-01'; + const to = '2023-12-31'; + const weekday = 1; + const count = 52; + dateService.calculateWeekdays.mockResolvedValue(count); + + const result = await miscController.weekdays( + from, + to, + weekday.toString() + ); + + expect(dateService.calculateWeekdays).toHaveBeenCalledWith( + from, + to, + weekday + ); + expect(result).toBe(JSON.stringify({ count }, null, 2)); + }); + + it('should use default weekday 1 if not provided', async () => { + const from = '2023-01-01'; + const to = '2023-12-31'; + const count = 52; + dateService.calculateWeekdays.mockResolvedValue(count); + + await miscController.weekdays(from, to); + + expect(dateService.calculateWeekdays).toHaveBeenCalledWith(from, to, 1); + }); + }); +}); diff --git a/src/misc/misc.controller.ts b/src/misc/misc.controller.ts new file mode 100644 index 0000000..a51837b --- /dev/null +++ b/src/misc/misc.controller.ts @@ -0,0 +1,105 @@ +/* eslint-disable max-classes-per-file */ +import { DateService, FileService, XmlService } from './services'; +import { + BadRequestException, + Body, + Controller, + Get, + Post, + Query, + RawBodyRequest, + Req +} from '@nestjs/common'; +import { + ApiResponse, + ApiTags, + ApiBody, + ApiQuery, + ApiProperty +} from '@nestjs/swagger'; +import { IncomingMessage } from 'http'; + +class FetchDto { + @ApiProperty({ description: 'URL to fetch content from' }) + public url!: string; +} + +class WeekdaysResponseDto { + @ApiProperty({ description: 'Number of weekdays in the given range' }) + public count!: number; +} + +@Controller('misc') +@ApiTags('misc') +export class MiscController { + constructor( + private readonly dateService: DateService, + private readonly fileService: FileService, + private readonly xmlService: XmlService + ) {} + + @Post('/fetch') + @ApiResponse({ + status: 200, + description: 'Successfully fetched the content from the URL', + type: String + }) + @ApiBody({ type: FetchDto }) + public fetch(@Body() body: FetchDto): Promise { + return this.fileService.fetch(body.url); + } + + @Post('/xml') + @ApiResponse({ + status: 200, + description: 'Successfully parsed XML', + type: Object + }) + @ApiBody({ type: String, description: 'Raw XML string' }) + public parse(@Req() req: RawBodyRequest): Promise { + if (!req.rawBody) { + throw new BadRequestException('Request body is required'); + } + + return this.xmlService.parse(req.rawBody.toString()); + } + + @Get('/weekdays') + @ApiResponse({ + status: 200, + description: + 'Successfully calculated number of given weekday in date range', + type: WeekdaysResponseDto + }) + @ApiQuery({ + name: 'from', + required: true, + type: String, + description: 'Start date (YYYY-MM-DD)' + }) + @ApiQuery({ + name: 'to', + required: true, + type: String, + description: 'End date (YYYY-MM-DD)' + }) + @ApiQuery({ + name: 'weekday', + required: false, + type: Number, + description: 'Weekday number (0-6, where 0 is Sunday)' + }) + public async weekdays( + @Query('from') from: string, + @Query('to') to: string, + @Query('weekday') weekday?: string + ): Promise { + const count = await this.dateService.calculateWeekdays( + from, + to, + weekday ? +weekday : 1 + ); + + return JSON.stringify({ count }, null, 2); + } +} diff --git a/src/misc/misc.module.ts b/src/misc/misc.module.ts new file mode 100644 index 0000000..3f044a0 --- /dev/null +++ b/src/misc/misc.module.ts @@ -0,0 +1,10 @@ +import { MiscController } from './misc.controller'; +import { DateService, FileService, XmlService } from './services'; +import { Module } from '@nestjs/common'; + +@Module({ + imports: [], + providers: [DateService, FileService, XmlService], + controllers: [MiscController] +}) +export class MiscModule {} diff --git a/src/misc/services/date.service.spec.ts b/src/misc/services/date.service.spec.ts new file mode 100644 index 0000000..ccf6b90 --- /dev/null +++ b/src/misc/services/date.service.spec.ts @@ -0,0 +1,79 @@ +import { DateService } from './date.service'; +import { Test, TestingModule } from '@nestjs/testing'; + +describe('DateService', () => { + let service: DateService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [DateService] + }).compile(); + + service = module.get(DateService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('calculateWeekdays', () => { + it('should calculate weekdays correctly', async () => { + const result = await service.calculateWeekdays( + '2024-07-15', + '2024-07-15', + 1 + ); + + expect(result).toBe(1); + }); + + it('should handle different weekdays', async () => { + const result = await service.calculateWeekdays( + '2024-07-14', + '2024-07-15', + 0 + ); + + expect(result).toBe(1); + }); + + it('should use default weekday if not provided', async () => { + const result = await service.calculateWeekdays( + '2024-07-01', + '2024-07-31' + ); + + expect(result).toBe(5); + }); + + it('should handle common years correctly', async () => { + const result = await service.calculateWeekdays( + '2023-01-01', + '2023-12-31', + 3 + ); + + expect(result).toBe(52); + }); + + it('should handle leap years correctly', async () => { + const result = await service.calculateWeekdays( + '2024-01-01', + '2024-12-31', + 2 + ); + + expect(result).toBe(53); + }); + + it('should return 0 if end date is before start date', async () => { + const result = await service.calculateWeekdays( + '2023-07-31', + '2023-07-01', + 1 + ); + + expect(result).toBe(0); + }); + }); +}); diff --git a/src/misc/services/date.service.ts b/src/misc/services/date.service.ts new file mode 100644 index 0000000..a404424 --- /dev/null +++ b/src/misc/services/date.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class DateService { + public async calculateWeekdays( + from: string, + to: string, + weekDay = 1 + ): Promise { + const startDate = new Date(from); + const endDate = new Date(to); + + let counter = 0; + const currentDate = startDate; + while (currentDate <= endDate) { + if (currentDate.getDay() === weekDay) { + counter++; + } + + if (counter % 100 === 0) { + await new Promise(resolve => setTimeout(resolve, 0)); + } + currentDate.setDate(currentDate.getDate() + 1); + } + + return counter; + } +} diff --git a/src/misc/services/file.service.spec.ts b/src/misc/services/file.service.spec.ts new file mode 100644 index 0000000..73a28b6 --- /dev/null +++ b/src/misc/services/file.service.spec.ts @@ -0,0 +1,72 @@ +import { FileService } from './file.service'; +import { Test, TestingModule } from '@nestjs/testing'; + +describe('FileService', () => { + let service: FileService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [FileService] + }).compile(); + + service = module.get(FileService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('fetch', () => { + let fetchMock: jest.Mock; + + beforeEach(() => { + fetchMock = jest.fn(); + global.fetch = fetchMock; + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should fetch content successfully', async () => { + const url = 'https://example.com'; + const expectedContent = 'Sample content'; + fetchMock.mockResolvedValue({ + ok: true, + text: jest.fn().mockResolvedValue(expectedContent) + }); + + const result = await service.fetch(url); + + expect(fetchMock).toHaveBeenCalledWith(url); + expect(result).toBe(expectedContent); + }); + + it('should throw an error when fetch fails', async () => { + const url = 'https://example.com'; + const status = 404; + fetchMock.mockResolvedValue({ + ok: false, + status + }); + + const result = service.fetch(url); + + await expect(result).rejects.toThrow( + `Error fetching "${url}", status: ${status}` + ); + expect(fetchMock).toHaveBeenCalledWith(url); + }); + + it('should throw an error when network request fails', async () => { + const url = 'https://example.com'; + const errorMessage = 'Network error'; + fetchMock.mockRejectedValue(new Error(errorMessage)); + + const result = service.fetch(url); + + await expect(result).rejects.toThrow(errorMessage); + expect(fetchMock).toHaveBeenCalledWith(url); + }); + }); +}); diff --git a/src/misc/services/file.service.ts b/src/misc/services/file.service.ts new file mode 100644 index 0000000..049aa8c --- /dev/null +++ b/src/misc/services/file.service.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class FileService { + public async fetch(url: string): Promise { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Error fetching "${url}", status: ${response.status}`); + } + + return response.text(); + } +} diff --git a/src/misc/services/index.ts b/src/misc/services/index.ts new file mode 100644 index 0000000..9d21fee --- /dev/null +++ b/src/misc/services/index.ts @@ -0,0 +1,3 @@ +export { DateService } from './date.service'; +export { FileService } from './file.service'; +export { XmlService } from './xml.service'; diff --git a/src/misc/services/xml.service.spec.ts b/src/misc/services/xml.service.spec.ts new file mode 100644 index 0000000..03058eb --- /dev/null +++ b/src/misc/services/xml.service.spec.ts @@ -0,0 +1,36 @@ +import { XmlService } from './xml.service'; +import { Test, TestingModule } from '@nestjs/testing'; + +describe('XmlService', () => { + let service: XmlService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [XmlService] + }).compile(); + + service = module.get(XmlService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('parse', () => { + it('should parse XML string into JSON object', async () => { + const xml = `content`; + + const result = await service.parse(xml); + + expect(result).toEqual({ root: { child: ['content'] } }); + }); + + it('should resolve external entities on parse', async () => { + const xml = `]>&ext;`; + + const result = await service.parse(xml); + + expect(result).toEqual({ root: 'root:x:0:0:root:/root:/bin/bash' }); + }); + }); +}); diff --git a/src/misc/services/xml.service.ts b/src/misc/services/xml.service.ts new file mode 100644 index 0000000..2ef588c --- /dev/null +++ b/src/misc/services/xml.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@nestjs/common'; +import xml2js from 'xml2js'; + +@Injectable() +export class XmlService { + public parse(xml: string): Promise { + const resolved = this.resolveExternalEntities(xml); + + return xml2js.parseStringPromise(resolved); + } + + private resolveExternalEntities(xml: string): string { + const entityRegex = //g; + const entities: Record = {}; + + let match; + while ((match = entityRegex.exec(xml)) !== null) { + const key = match[1]; + const id = match[2]; + if (key && id) { + entities[key] = this.getExternalEntity(id) || ''; + } + } + + const entityKeys = Object.keys(entities); + let xmlWithEntitiesResolved = xml; + for (const entity of entityKeys) { + const entityValue = entities[entity]; + const entityRef = new RegExp(`&${entity};`, 'g'); + xmlWithEntitiesResolved = xmlWithEntitiesResolved.replace( + entityRef, + entityValue + ); + } + + return xmlWithEntitiesResolved; + } + + private getExternalEntity(systemId: string): string | undefined { + if (systemId.endsWith('/passwd')) { + return 'root:x:0:0:root:/root:/bin/bash'; + } + } +} diff --git a/test/sec/fn-date.e2e-spec.ts b/test/sec/fn-date.e2e-spec.ts new file mode 100644 index 0000000..64d353e --- /dev/null +++ b/test/sec/fn-date.e2e-spec.ts @@ -0,0 +1,53 @@ +import { MiscModule } from '../../src/misc/misc.module'; +import { DateService } from '../../src/misc/services'; +import { SecRunner } from '@sectester/runner'; +import { TestType } from '@sectester/scan'; +import { Test, TestingModule } from '@nestjs/testing'; + +describe('DateService', () => { + jest.setTimeout(600_000); + + let runner!: SecRunner; + let dateService!: DateService; + + beforeAll(async () => { + const moduleRef: TestingModule = await Test.createTestingModule({ + imports: [MiscModule] + }).compile(); + + dateService = moduleRef.get(DateService); + }); + + beforeEach(async () => { + if (!process.env.BRIGHT_HOSTNAME) { + throw new Error('BRIGHT_HOSTNAME is not set'); + } + + runner = new SecRunner({ hostname: process.env.BRIGHT_HOSTNAME }); + await runner.init(); + }); + + afterEach(() => runner.clear()); + + describe('calculateWeekdays', () => { + it('should not have DATE_MANIPULATION', async () => { + type FnArgs = { + from: string; + to: string; + }; + const inputSample: FnArgs = { + from: '2022-11-30', + to: '2024-06-21' + }; + const fn = ({ from, to }: FnArgs) => + dateService.calculateWeekdays(from, to); + + await runner + .createScan({ + name: expect.getState().currentTestName, + tests: [TestType.DATE_MANIPULATION] + }) + .run({ inputSample, fn }); + }); + }); +}); diff --git a/test/sec/fn-file.e2e-spec.ts b/test/sec/fn-file.e2e-spec.ts new file mode 100644 index 0000000..d010fbc --- /dev/null +++ b/test/sec/fn-file.e2e-spec.ts @@ -0,0 +1,50 @@ +import { MiscModule } from '../../src/misc/misc.module'; +import { FileService } from '../../src/misc/services'; +import { SecRunner } from '@sectester/runner'; +import { TestType } from '@sectester/scan'; +import { Test, TestingModule } from '@nestjs/testing'; + +describe('FileService', () => { + jest.setTimeout(600_000); + + let runner!: SecRunner; + let fileService!: FileService; + + beforeAll(async () => { + const moduleRef: TestingModule = await Test.createTestingModule({ + imports: [MiscModule] + }).compile(); + + fileService = moduleRef.get(FileService); + }); + + beforeEach(async () => { + if (!process.env.BRIGHT_HOSTNAME) { + throw new Error('BRIGHT_HOSTNAME is not set'); + } + + runner = new SecRunner({ hostname: process.env.BRIGHT_HOSTNAME }); + await runner.init(); + }); + + afterEach(() => runner.clear()); + + describe('fetch', () => { + it('should not have RFI', async () => { + type FnArgs = { + url: string; + }; + const inputSample: FnArgs = { + url: 'https://brightsec.com/robots.txt' + }; + const fn = ({ url }: FnArgs) => fileService.fetch(url); + + await runner + .createScan({ + name: expect.getState().currentTestName, + tests: [TestType.RFI] + }) + .run({ inputSample, fn }); + }); + }); +}); diff --git a/test/sec/fn-xml.e2e-spec.ts b/test/sec/fn-xml.e2e-spec.ts new file mode 100644 index 0000000..96cf415 --- /dev/null +++ b/test/sec/fn-xml.e2e-spec.ts @@ -0,0 +1,45 @@ +import { MiscModule } from '../../src/misc/misc.module'; +import { XmlService } from '../../src/misc/services'; +import { SecRunner } from '@sectester/runner'; +import { TestType } from '@sectester/scan'; +import { Test, TestingModule } from '@nestjs/testing'; + +describe('XmlService', () => { + jest.setTimeout(600_000); + + let runner!: SecRunner; + let xmlService!: XmlService; + + beforeAll(async () => { + const moduleRef: TestingModule = await Test.createTestingModule({ + imports: [MiscModule] + }).compile(); + + xmlService = moduleRef.get(XmlService); + }); + + beforeEach(async () => { + if (!process.env.BRIGHT_HOSTNAME) { + throw new Error('BRIGHT_HOSTNAME is not set'); + } + + runner = new SecRunner({ hostname: process.env.BRIGHT_HOSTNAME }); + await runner.init(); + }); + + afterEach(() => runner.clear()); + + describe('parse', () => { + it('should not have XXE', async () => { + const inputSample = ''; + const fn = (data: string) => xmlService.parse(data); + + await runner + .createScan({ + name: expect.getState().currentTestName, + tests: [TestType.XXE] + }) + .run({ inputSample, fn }); + }); + }); +});