diff --git a/.eslintrc.js b/.eslintrc.js index 8f5aedb..0960956 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,5 +21,6 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', + 'prettier/prettier': 0, }, }; diff --git a/.gitignore b/.gitignore index 22f55ad..1a620ca 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,8 @@ lerna-debug.log* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json -!.vscode/extensions.json \ No newline at end of file +!.vscode/extensions.json + +#Environment +.env +.vscode/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ce7556f..4745026 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,9 @@ "@nestjs/passport": "^9.0.0", "@nestjs/platform-express": "^9.0.0", "@nestjs/typeorm": "^9.0.1", + "bcrypt": "^5.1.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.13.2", "hbs": "^4.2.0", "mysql2": "^2.3.3", "passport": "^0.6.0", @@ -29,6 +32,7 @@ "@nestjs/cli": "^9.0.0", "@nestjs/schematics": "^9.0.0", "@nestjs/testing": "^9.0.0", + "@types/bcrypt": "^5.0.0", "@types/express": "^4.17.13", "@types/jest": "28.1.8", "@types/node": "^16.0.0", @@ -1433,6 +1437,25 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@nestjs/cli": { "version": "9.1.5", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.1.5.tgz", @@ -1887,6 +1910,15 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -2495,6 +2527,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2546,6 +2583,17 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", @@ -2668,6 +2716,36 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -2836,6 +2914,19 @@ } ] }, + "node_modules/bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3130,6 +3221,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -3151,6 +3250,20 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "node_modules/class-validator": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz", + "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==", + "dependencies": { + "libphonenumber-js": "^1.9.43", + "validator": "^13.7.0" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3323,6 +3436,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3374,6 +3495,11 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -3541,6 +3667,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -3566,6 +3697,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -4481,6 +4620,17 @@ "node": ">=12" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", @@ -4511,6 +4661,25 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -4712,6 +4881,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hbs": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hbs/-/hbs-4.2.0.tgz", @@ -4763,6 +4937,18 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -6131,6 +6317,11 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.14.tgz", + "integrity": "sha512-McGS7GV/WjJ2KjfOGhJU1oJn29RYeo7Q+RpANRbUNMQ9gj5XArpbjurSuyYPTejFwbaUojstQ4XyWCrAzGOUXw==" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -6290,7 +6481,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -6305,7 +6495,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -6444,6 +6633,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -6578,6 +6790,11 @@ "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", "dev": true }, + "node_modules/node-addon-api": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz", + "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==" + }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -6618,6 +6835,20 @@ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6639,6 +6870,17 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7549,7 +7791,6 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -7629,6 +7870,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -7700,8 +7946,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sisteransi": { "version": "1.0.5", @@ -7983,6 +8228,33 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.1.12", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.12.tgz", + "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -8724,6 +8996,14 @@ "node": ">=10.12.0" } }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -8865,6 +9145,14 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/windows-release": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", @@ -10144,6 +10432,22 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + } + }, "@nestjs/cli": { "version": "9.1.5", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.1.5.tgz", @@ -10468,6 +10772,15 @@ "@babel/types": "^7.3.0" } }, + "@types/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -10987,6 +11300,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -11022,6 +11340,14 @@ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "devOptional": true }, + "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==", + "requires": { + "debug": "4" + } + }, "ajv": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", @@ -11104,6 +11430,32 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -11230,6 +11582,15 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + } + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -11440,6 +11801,11 @@ "readdirp": "~3.6.0" } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -11458,6 +11824,20 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "class-validator": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz", + "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==", + "requires": { + "libphonenumber-js": "^1.9.43", + "validator": "^13.7.0" + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -11583,6 +11963,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -11625,6 +12010,11 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -11750,6 +12140,11 @@ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -11765,6 +12160,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -12470,6 +12870,14 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, "fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", @@ -12493,6 +12901,22 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, "generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -12634,6 +13058,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "hbs": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hbs/-/hbs-4.2.0.tgz", @@ -12672,6 +13101,15 @@ "toidentifier": "1.0.1" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -13703,6 +14141,11 @@ "type-check": "~0.4.0" } }, + "libphonenumber-js": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.14.tgz", + "integrity": "sha512-McGS7GV/WjJ2KjfOGhJU1oJn29RYeo7Q+RpANRbUNMQ9gj5XArpbjurSuyYPTejFwbaUojstQ4XyWCrAzGOUXw==" + }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -13831,7 +14274,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "requires": { "semver": "^6.0.0" }, @@ -13839,8 +14281,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -13942,6 +14383,23 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" }, + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, "mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -14062,6 +14520,11 @@ "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", "dev": true }, + "node-addon-api": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz", + "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==" + }, "node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -14091,6 +14554,14 @@ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -14106,6 +14577,17 @@ "path-key": "^3.0.0" } }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -14754,7 +15236,6 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -14826,6 +15307,11 @@ "send": "0.18.0" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -14879,8 +15365,7 @@ "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "sisteransi": { "version": "1.0.5", @@ -15095,6 +15580,26 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true }, + "tar": { + "version": "6.1.12", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.12.tgz", + "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -15533,6 +16038,11 @@ "convert-source-map": "^1.6.0" } }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -15641,6 +16151,14 @@ "isexe": "^2.0.0" } }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "windows-release": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", diff --git a/package.json b/package.json index 2f3238b..fc1fcbb 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,9 @@ "@nestjs/passport": "^9.0.0", "@nestjs/platform-express": "^9.0.0", "@nestjs/typeorm": "^9.0.1", + "bcrypt": "^5.1.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.13.2", "hbs": "^4.2.0", "mysql2": "^2.3.3", "passport": "^0.6.0", @@ -41,6 +44,7 @@ "@nestjs/cli": "^9.0.0", "@nestjs/schematics": "^9.0.0", "@nestjs/testing": "^9.0.0", + "@types/bcrypt": "^5.0.0", "@types/express": "^4.17.13", "@types/jest": "28.1.8", "@types/node": "^16.0.0", diff --git a/src/app.controller.ts b/src/app.controller.ts index b2f40a8..259c6d3 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,3 +1,4 @@ +/* eslint-disable prettier/prettier */ import { Controller, Get, Post, Request, UseGuards } from '@nestjs/common'; import { AuthService } from './auth/auth.service'; import { JwtAuthGuard } from './auth/guards/jwt-auth.guard'; @@ -7,8 +8,6 @@ import { LocalAuthGuard } from './auth/guards/local-auth.guard'; export class AppController { constructor(private readonly authService: AuthService) {} - - @UseGuards(JwtAuthGuard) @Get('profile') getProfile(@Request() req) { diff --git a/src/app.module.ts b/src/app.module.ts index e7e9ad3..9bf52bc 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -11,22 +11,29 @@ import { QuestionModule } from './modules/question/question.module'; import { ExamModule } from './modules/exam/exam.module'; import { ExamHistory } from './modules/examHistory/entities/ExamHistory'; import { AuthModule } from './auth/auth.module'; - +require('dotenv').config(); +import { PostRefactoring1669709884520 } from './migrations/1669709884520-PostRefactoring'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', - host: 'localhost', - port: 3306, - username: 'root', - password: '123456', - database: 'lms', - entities: [Question,User,Exam,ExamHistory], - synchronize: true, - dropSchema: false - }),QuestionModule,ExamModule, AuthModule,UserModule + host: process.env.HOST, + port: Number(process.env.PORT), + username: process.env.DBUSERNAME, + password: process.env.PASSWORD, + database: process.env.DATABASE, + entities: [Question, User, Exam, ExamHistory], + migrations: [PostRefactoring1669709884520], + migrationsTableName: 'migrations', + synchronize: false, + dropSchema: false, + }), + QuestionModule, + ExamModule, + AuthModule, + UserModule, ], controllers: [AppController], providers: [AppService], }) -export class AppModule {} \ No newline at end of file +export class AppModule {} diff --git a/src/app.service.ts b/src/app.service.ts index 927d7cc..fb7435c 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -1,8 +1,10 @@ import { Injectable } from '@nestjs/common'; + @Injectable() export class AppService { getHello(): string { return 'Hello World!'; } + } diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 997287f..621449d 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -4,10 +4,10 @@ import { LocalAuthGuard } from './guards/local-auth.guard'; @Controller('auth') export class AuthController { - constructor(private readonly authService: AuthService) {} - @UseGuards(LocalAuthGuard) - @Post('login') - async login(@Request() req) { - return this.authService.login(req.user); - } + constructor(private readonly authService: AuthService) {} + @UseGuards(LocalAuthGuard) + @Post('login') + async login(@Request() req) { + return this.authService.login(req.user); + } } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index e44017d..deaf99f 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { UserService } from 'src/modules/user/user.service'; import { JwtService } from '@nestjs/jwt'; +import { compare } from 'bcrypt'; @Injectable() export class AuthService { @@ -10,8 +11,9 @@ export class AuthService { ) {} async validateUser(email: string, pass: string): Promise { - const user = await this.usersService.findOnename(email); - if (user && user.password == pass) { + const user = await this.usersService.findOneName(email); + + if (user && (await compare(pass, user.password))) { const { password, ...result } = user; return result; } diff --git a/src/data-source.ts b/src/data-source.ts new file mode 100644 index 0000000..e560676 --- /dev/null +++ b/src/data-source.ts @@ -0,0 +1,25 @@ +import { DataSource } from "typeorm/data-source/DataSource"; +import { PostRefactoring1669709884520 } from "./migrations/1669709884520-PostRefactoring"; +import { Exam } from "./modules/exam/entities/exam.entity"; +import { ExamHistory } from "./modules/examHistory/entities/ExamHistory"; +import { Question } from "./modules/question/entities/question.entity"; +import { User } from "./modules/user/entities/user.entity"; + + const AppDataSource = new DataSource({ + type: 'mysql', + host: process.env.HOST, + port: Number(process.env.PORT), + username: process.env.DBUSERNAME, + password: process.env.PASSWORD, + database: process.env.DATABASE, + entities: [Question,User,Exam,ExamHistory], + migrations: [PostRefactoring1669709884520], + migrationsTableName: "migrations", + synchronize: false, + dropSchema: false +}) +AppDataSource.initialize() + .then(() => { + // here you can start to work with your database + }) + .catch((error) => console.log(error)) \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 2e826f4..df2b778 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,17 +1,14 @@ +import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; -import { join } from 'path'; + import { AppModule } from './app.module'; async function bootstrap() { - const app = await NestFactory.create( - AppModule, - ); + const app = await NestFactory.create(AppModule); + + app.useGlobalPipes(new ValidationPipe()); - app.useStaticAssets(join(__dirname, '..', 'public')); - app.setBaseViewsDir(join(__dirname, '..', 'views')); - app.setViewEngine('hbs'); - app.enableCors(); await app.listen(3000); } -bootstrap(); \ No newline at end of file +bootstrap(); diff --git a/src/migrations/1669709884520-PostRefactoring.ts b/src/migrations/1669709884520-PostRefactoring.ts new file mode 100644 index 0000000..2f0765d --- /dev/null +++ b/src/migrations/1669709884520-PostRefactoring.ts @@ -0,0 +1,91 @@ +import { + MigrationInterface, + QueryRunner, + Table, + TableIndex, + TableColumn, + TableForeignKey, +} from 'typeorm'; + +export class PostRefactoring1669709884520 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable( + new Table({ + name: 'question', + columns: [ + { + name: 'id', + type: 'int', + isPrimary: true, + }, + { + name: 'name', + type: 'varchar', + }, + ], + }), + true, + ); + + await queryRunner.createIndex( + 'question', + new TableIndex({ + name: 'IDX_QUESTION_NAME', + columnNames: ['name'], + }), + ); + + await queryRunner.createTable( + new Table({ + name: 'answer', + columns: [ + { + name: 'id', + type: 'int', + isPrimary: true, + }, + { + name: 'name', + type: 'varchar', + }, + { + name: 'created_at', + type: 'timestamp', + default: 'now()', + }, + ], + }), + true, + ); + + await queryRunner.addColumn( + 'answer', + new TableColumn({ + name: 'questionId', + type: 'int', + }), + ); + + await queryRunner.createForeignKey( + 'answer', + new TableForeignKey({ + columnNames: ['questionId'], + referencedColumnNames: ['id'], + referencedTableName: 'question', + onDelete: 'CASCADE', + }), + ); + } + + async down(queryRunner: QueryRunner): Promise { + const table = await queryRunner.getTable('answer'); + const foreignKey = table.foreignKeys.find( + (fk) => fk.columnNames.indexOf('questionId') !== -1, + ); + await queryRunner.dropForeignKey('answer', foreignKey); + await queryRunner.dropColumn('answer', 'questionId'); + await queryRunner.dropTable('answer'); + await queryRunner.dropIndex('question', 'IDX_QUESTION_NAME'); + await queryRunner.dropTable('question'); + } +} diff --git a/src/modules/exam/dto/create-exam.dto.ts b/src/modules/exam/dto/create-exam.dto.ts index 335bf7e..69c60f8 100644 --- a/src/modules/exam/dto/create-exam.dto.ts +++ b/src/modules/exam/dto/create-exam.dto.ts @@ -1,5 +1,12 @@ +import { + IsEmail, + IsNotEmpty, +} from 'class-validator'; export class CreateExamDto { - examName:string; - timeLimit:number; - subjectId:number; + @IsNotEmpty() + examName: string; + @IsNotEmpty() + timeLimit: number; + @IsNotEmpty() + subjectId: number; } diff --git a/src/modules/exam/exam.controller.ts b/src/modules/exam/exam.controller.ts index 21668ae..59929f2 100644 --- a/src/modules/exam/exam.controller.ts +++ b/src/modules/exam/exam.controller.ts @@ -9,10 +9,14 @@ import { Req, Request, UseGuards, + Query, } from '@nestjs/common'; import { ExamService } from './exam.service'; import { CreateExamDto } from './dto/create-exam.dto'; -import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'; +import { Question } from '../question/entities/question.entity'; +import { Exam } from './entities/exam.entity'; +import { ExamHistory } from '../examHistory/entities/ExamHistory'; +import { DeleteResult } from 'typeorm'; //@UseGuards(JwtAuthGuard) @Controller('exam') @@ -20,48 +24,55 @@ export class ExamController { constructor(private readonly examService: ExamService) {} @Get('doexam/:id') - doexam(@Param('id') id: string) { + doexam(@Param('id') id: string): Promise { return this.examService.doExam(parseInt(id)); } @Post('result/:ide/:idu') getResult( - @Param('ide') ide: number, - @Param('idu') idu: number, + @Param('ide') idExam: number, + @Param('idu') idUser: number, @Body() Body, - ) { - return this.examService.getResult(ide, idu, Body); + ): Promise { + return this.examService.getResult(idExam, idUser, Body); } @Post() - create(@Body() createExamDto: CreateExamDto) { + create(@Body() createExamDto: CreateExamDto): Promise { return this.examService.create(createExamDto); } @Get() - findAll() { - return this.examService.findAll(); + findAll(@Query('page') page: number) { + const query = { + keyword: '', + take: 5, + page: page, + }; + return this.examService.findAll(query); } @Get(':id') - findOne(@Param('id') id: number) { + findOne(@Param('id') id: number): Promise { return this.examService.findOne(id); } @Get('rank/:id') - rank(@Param('id') id: number) { + rank(@Param('id') id: number): Promise { return this.examService.rank(id); } @Patch(':id') - update(@Param('id') id: string, @Body() createExamDto: CreateExamDto) { + update( + @Param('id') id: string, + @Body() createExamDto: CreateExamDto, + ): Promise { return this.examService.update(parseInt(id), createExamDto); } @Delete(':id') - remove(@Param('id') id: string) { + remove(@Param('id') id: string): Promise { return this.examService.remove(+id); } @Get('history/:id') - getHistory(@Param('id') id:number) { + getHistory(@Param('id') id: number): Promise { return this.examService.getHistory(id); } - } diff --git a/src/modules/exam/exam.service.ts b/src/modules/exam/exam.service.ts index 4c9a779..fa19a3c 100644 --- a/src/modules/exam/exam.service.ts +++ b/src/modules/exam/exam.service.ts @@ -15,31 +15,43 @@ export class ExamService { @InjectDataSource() private dataSource: DataSource, ) {} - findAll(): Promise { - return this.examRepository.find(); - } + async findAll(query) { + const take = query.take; + const page = query.page; + const skip = (page - 1) * take; + + const [result, total] = await this.examRepository.findAndCount({ + // where: { questionname: Like('%' + keyword + '%') }, //order: { questionname: "DESC" }, + take: take, + skip: skip, + }); - async findOne(id: number) { - let exam = await this.examRepository.findOneBy({ examId: id }); + return { + data: result, + count: total, + }; + } + async findOne(id: number): Promise { + const exam = await this.examRepository.findOneBy({ examId: id }); return exam; } - - create(createExamDto: CreateExamDto) { + + create(createExamDto: CreateExamDto): Promise { return this.examRepository.save(createExamDto); } - update(id: number, createExamDto: CreateExamDto) { + update(id: number, createExamDto: CreateExamDto): Promise { createExamDto['examId'] = id; return this.examRepository.save(createExamDto); } remove(id: number): Promise { return this.examRepository.delete(id); } - // ham tra ve 1 set gom 4 phan tu random giua 2 so nguyen n va m - getRandom(n, m) { - const myset = new Set(); + // ham tra ve 1 set gom 4 phan tu random giua 2 so nguyen start va end + getRandom(start, end): Set { + const myset = new Set(); for (let i = 0; i < 20; i++) { - let num = Math.floor(Math.random() * (m + 1 - n)) + n; + const num = Number(Math.floor(Math.random() * (end + 1 - start)) + start); myset.add(num); if (myset.size == 4) break; } @@ -47,16 +59,16 @@ export class ExamService { } //Lam bai theo id de, ngau nhien ham tra ve 4 cau hoi - async doExam(id: number) { + async doExam(id: number): Promise { const question1 = await this.dataSource.manager .createQueryBuilder(Question, 'question') .where('question.examId = :id1', { id1: id }) .getMany(); - let q2 = this.getRandom(0, question1.length - 1); - let q3 = Array.from(q2); - let q4 = []; + const q2 = this.getRandom(0, question1.length - 1); + const q3 = Array.from(q2); + const q4 = []; for (let i = 0; i < 4; i++) { - let q5 = parseInt('' + q3[i]); + const q5 = parseInt('' + q3[i]); q4.push(question1[q5]); } @@ -64,43 +76,43 @@ export class ExamService { return q4; } - async getResult(ide: number, idu: number, Body) { + async getResult(idExam: number, idUser: number, Body): Promise { let point = 0; - for (var key in Body) { + for (const key in Body) { if (Body.hasOwnProperty(key)) { - let value = Body[key]; + const value = Body[key]; const question1 = await this.dataSource.manager .createQueryBuilder(Question, 'question') - .where('question.id = :id1', { id1: key }) + .where('question.id = :id', { id: key }) .getOne(); - if (value == question1.correctanswer) point++; + if (value == question1.correctAnswer) point++; } } const q2 = await this.dataSource .createQueryBuilder() .insert() .into(ExamHistory) - .values([{ userId: idu, examId: ide, score: point }]) + .values([{ userId: idUser, examId: idExam, score: point }]) .execute(); return point; } - async getHistory(id:number) { - let history = await this.dataSource.manager - .createQueryBuilder(ExamHistory, 'examhistory') - .where('examhistory.userId=:userid',{userid:id}) - .getMany() + async getHistory(id: number): Promise { + const history = await this.dataSource.manager + .createQueryBuilder(ExamHistory, 'examhistory') + .where('examhistory.userId=:userId', { userId: id }) + .getMany(); console.log(history); return history; } - async rank(ide: number) { - var data = this.dataSource; - let rank1 = await this.dataSource.manager + async rank(ide: number): Promise { + const data = this.dataSource; + const listrank = await this.dataSource.manager .createQueryBuilder(ExamHistory, 'examhistory') .where('examhistory.examId =:score', { score: ide }) .orderBy('score', 'DESC') .getMany(); - let rank = await this.dataSource.manager + const rank = await this.dataSource.manager .createQueryBuilder(User, 'user') .leftJoinAndSelect( @@ -111,13 +123,14 @@ export class ExamService { .where('examhistory.examId =:score', { score: ide }) .orderBy('score', 'DESC') .getMany(); - - rank1.forEach(element => { - let user=rank.find(function(a) {return element.userId==a.userId}) - element['username']=user.username; + + listrank.forEach((element) => { + const user = rank.find(function (a) { + return element.userId == a.userId; + }); + element['username'] = user.userName; }); - return rank1; + return listrank; } - } diff --git a/src/modules/question/dto/create-question.dto.ts b/src/modules/question/dto/create-question.dto.ts index 2963866..2d3d9c1 100644 --- a/src/modules/question/dto/create-question.dto.ts +++ b/src/modules/question/dto/create-question.dto.ts @@ -1,10 +1,20 @@ +import { IsInt, IsNotEmpty, Length, Max, Min } from 'class-validator'; + export class CreateQuestionDto { - questionname:string; - difficultlevel:number; - answer1:string; - answer2:string; - answer3:string; - correctanswer:number; - - + @IsNotEmpty() + questionName: string; + @IsNotEmpty() + @IsInt() + @Min(1) + @Max(3) + difficultLevel: number; + @IsNotEmpty() + @Length(5, 10) + answer1: string; + @IsNotEmpty() + answer2: string; + @IsNotEmpty() + answer3: string; + @IsNotEmpty() + correctAnswer: number; } diff --git a/src/modules/question/entities/question.entity.ts b/src/modules/question/entities/question.entity.ts index 73b8827..87b69dd 100644 --- a/src/modules/question/entities/question.entity.ts +++ b/src/modules/question/entities/question.entity.ts @@ -6,9 +6,9 @@ export class Question { id: number; @Column() - questionname: string; + questionName: string; @Column() - difficultlevel: number; + difficultLevel: number; @Column() answer1: string; @@ -18,7 +18,7 @@ export class Question { @Column() answer3: string; @Column() - correctanswer: number; + correctAnswer: number; @Column() examId: number; @Column({ default: true}) diff --git a/src/modules/question/question.controller.ts b/src/modules/question/question.controller.ts index 3539c64..3657198 100644 --- a/src/modules/question/question.controller.ts +++ b/src/modules/question/question.controller.ts @@ -1,42 +1,49 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards } from '@nestjs/common'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, + UseGuards, + Query, +} from '@nestjs/common'; import { QuestionService } from './question.service'; import { CreateQuestionDto } from './dto/create-question.dto'; import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'; +import { Question } from './entities/question.entity'; // @UseGuards(JwtAuthGuard) @Controller('question') export class QuestionController { constructor(private readonly questionService: QuestionService) {} - - @Post() - create(@Body() createQuestionDto: CreateQuestionDto) { + create(@Body() createQuestionDto: CreateQuestionDto): Promise { return this.questionService.create(createQuestionDto); } @Get() - findAll() { - return this.questionService.findAll(); + findAll(@Query('page') page: number) { + let query = { + keyword: '', + take: 5, // so luong ket qua trong 1 trang + page: page, + }; + return this.questionService.findAll(query); } @Get(':id') - findOne(@Param('id') id: string) { + findOne(@Param('id') id: string): Promise { return this.questionService.findOne(+id); } @Patch(':id') - update(@Param('id') id: string, @Body() updateQuestionDto: CreateQuestionDto) { + update( + @Param('id') id: string, + @Body() updateQuestionDto: CreateQuestionDto, + ): Promise { return this.questionService.update(+id, updateQuestionDto); } - - @Delete(':id') - remove(@Param('id') id: string) { - return this.questionService.remove(+id); - } -//// controller cho lam bai - - - - } diff --git a/src/modules/question/question.service.ts b/src/modules/question/question.service.ts index 22dbed5..9ccf4fd 100644 --- a/src/modules/question/question.service.ts +++ b/src/modules/question/question.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { CreateQuestionDto } from './dto/create-question.dto'; -import { Repository,DeleteResult, DataSource } from "typeorm"; +import { Repository, DataSource } from 'typeorm'; import { Question } from './entities/question.entity'; import { User } from '../user/entities/user.entity'; @@ -10,28 +10,38 @@ export class QuestionService { constructor( @InjectRepository(Question) private questionRepository: Repository, - @InjectDataSource() private dataSource: DataSource -){} - create(createQuestionDto: CreateQuestionDto) { + @InjectDataSource() private dataSource: DataSource, + ) {} + async findAll(query) { + const take = query.take; + const page = query.page; + const skip = (page - 1) * take; + const keyword = query.keyword || ''; - return this.questionRepository.save(createQuestionDto); - } + const [result, total] = await this.questionRepository.findAndCount({ + // where: { questionname: Like('%' + keyword + '%') }, //order: { questionname: "DESC" }, + take: take, + skip: skip, + }); - findAll() { - return this.questionRepository.find(); + return { + data: result, + count: total, + }; } - - findOne(id: number) { - return this.questionRepository.findOneBy({id:id}); + async create(createQuestionDto: CreateQuestionDto): Promise { + return await this.questionRepository.save(createQuestionDto); } - update(id: number, updateQuestionDto: CreateQuestionDto) { - updateQuestionDto['id']=id; - return this.questionRepository.save(updateQuestionDto); + async findOne(id: number): Promise { + return await this.questionRepository.findOneBy({ id: id }); } - remove(id: number) { - return `This action removes a #${id} question`; + async update( + id: number, + updateQuestionDto: CreateQuestionDto, + ): Promise { + updateQuestionDto['id'] = id; + return await this.questionRepository.save(updateQuestionDto); } - } diff --git a/src/modules/user/dto/create-user.dto.ts b/src/modules/user/dto/create-user.dto.ts index 919fdc7..f9b7acb 100644 --- a/src/modules/user/dto/create-user.dto.ts +++ b/src/modules/user/dto/create-user.dto.ts @@ -1,6 +1,21 @@ +import { + IsEmail, + IsNotEmpty, + IsNumber, + IsString, + MinLength, +} from 'class-validator'; + export class CreateUserDto { - username:string; - email:string; - password:string; - role:number; + @IsString() + @IsNotEmpty() + @MinLength(5) + userName: string; + @IsEmail() + @IsNotEmpty() + email: string; + @IsNotEmpty() + password: string; + @IsNumber() + role: number; } diff --git a/src/modules/user/dto/response-user.dto.ts b/src/modules/user/dto/response-user.dto.ts new file mode 100644 index 0000000..8c568a1 --- /dev/null +++ b/src/modules/user/dto/response-user.dto.ts @@ -0,0 +1,5 @@ +export class ResponseUserDto { + userName:string; + email:string; + role:number; +} diff --git a/src/modules/user/entities/user.entity.ts b/src/modules/user/entities/user.entity.ts index 4d7c097..87ad2e4 100644 --- a/src/modules/user/entities/user.entity.ts +++ b/src/modules/user/entities/user.entity.ts @@ -7,15 +7,14 @@ export class User { userId: number; @Column() - username: string; + userName: string; @Column() email: string; @Column() password: string; @Column({default:30}) role: number; - @OneToMany((type) => ExamHistory, (examHistory) => examHistory.userId) - examHistory: ExamHistory[] + diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index 41d9db0..7dd14f8 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -7,37 +7,53 @@ import { Param, Delete, UseGuards, + ValidationPipe, + UsePipes, + Query, } from '@nestjs/common'; import { UserService } from './user.service'; import { CreateUserDto } from './dto/create-user.dto'; import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'; +import { User } from './entities/user.entity'; +import { ResponseUserDto } from './dto/response-user.dto'; +import { DeleteResult } from 'typeorm/query-builder/result/DeleteResult'; // @UseGuards(JwtAuthGuard) @Controller('user') export class UserController { constructor(private readonly userService: UserService) {} @Post() - create(@Body() createUserDto: CreateUserDto) { + @UsePipes(ValidationPipe) + create(@Body() createUserDto: CreateUserDto): Promise { return this.userService.create(createUserDto); } @Get() - findAll() { - return this.userService.findAll(); + findAll(@Query('page') page: number) { + const query = { + keyword: '', + take: 5, // so luong ket qua trong 1 trang + page: page, + }; + + return this.userService.findAll(query); } @Get(':id') - findOne(@Param('id') id: string) { + findOne(@Param('id') id: string): Promise { return this.userService.findOne(id.toString()); } @Patch(':id') - update(@Param('id') id: string, @Body() updateUserDto: CreateUserDto) { + update( + @Param('id') id: string, + @Body() updateUserDto: CreateUserDto, + ): Promise { return this.userService.update(+id, updateUserDto); } @Delete(':id') - remove(@Param('id') id: string) { + remove(@Param('id') id: string): Promise { return this.userService.remove(+id); } } diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index 7e8566f..68280fa 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -3,33 +3,55 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository, DeleteResult } from 'typeorm'; import { CreateUserDto } from './dto/create-user.dto'; +import { ResponseUserDto } from './dto/response-user.dto'; + import { User } from './entities/user.entity'; +import { genSalt, hash } from 'bcrypt'; @Injectable() export class UserService { constructor(@InjectRepository(User) private userRepo: Repository) {} - create(createUserDto: CreateUserDto) { - return this.userRepo.save(createUserDto); + + async create(createUserDto: CreateUserDto): Promise { + const saltOrRounds = await genSalt(); + const passwordTemp = await hash(createUserDto.password, saltOrRounds); + createUserDto.password = passwordTemp; + const user = await this.userRepo.save(createUserDto); + const { password, ...result } = user; + return result; } - findAll(): Promise { - return this.userRepo.find(); + async findAll(query) { + const take = query.take; + const page = query.page; + const skip = (page - 1) * take; + + + const [result, total] = await this.userRepo.findAndCount({ + // where: { questionname: Like('%' + keyword + '%') }, //order: { questionname: "DESC" }, + take: take, + skip: skip, + }); + + return { + data: result, + count: total, + }; } - findOne(id: string): Promise { - return this.userRepo.findOneBy({ userId: parseInt(id) }); + async findOne(id: string): Promise { + return await this.userRepo.findOneBy({ userId: parseInt(id) }); } - findOnename(email: string): Promise { - - return this.userRepo.findOneBy({email: email}) + async findOneName(email: string): Promise { + return await this.userRepo.findOneBy({ email: email }); } - update(id: number, updateUserDto: CreateUserDto) { - updateUserDto['userId']=id; - return this.userRepo.save(updateUserDto); + async update(id: number, updateUserDto: CreateUserDto): Promise { + updateUserDto['userId'] = id; + return await this.userRepo.save(updateUserDto); } - remove(id: number): Promise { - return this.userRepo.delete(id); + async remove(id: number): Promise { + return await this.userRepo.delete(id); } } diff --git a/tsconfig.json b/tsconfig.json index adb614c..dac31ab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,7 @@ "strictNullChecks": false, "noImplicitAny": false, "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, "noFallthroughCasesInSwitch": false }