Showing
25 changed files
with
389 additions
and
95 deletions
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | "request": "launch", |
| 7 | 7 | "name": "Base-Debugger", |
| 8 | 8 | "runtimeExecutable": "npm", |
| 9 | - "runtimeArgs": ["run", "start:debug", "--", "--inspect-brk"], | |
| 9 | + "runtimeArgs": ["run", "start:dev:debug", "--", "--inspect-brk"], | |
| 10 | 10 | "autoAttachChildProcesses": true, |
| 11 | 11 | "restart": true, |
| 12 | 12 | "sourceMaps": true, | ... | ... |
environment/.env.dev
0 → 100644
| 1 | +# Environment variables declared in this file are automatically made available to Prisma. | |
| 2 | +# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema | |
| 3 | + | |
| 4 | +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. | |
| 5 | +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings | |
| 6 | + | |
| 7 | +DATABASE_URL="mysql://root:toor@localhost:3306/base-db" | |
| 8 | + | |
| 9 | +#TESTING DATABASE . CHANGE TO YOUR OWN DATA | |
| 10 | +DB_HOST=base-database | |
| 11 | +DB_ROOT_PASSWORD=toor | |
| 12 | +DB_NAME=base-db | |
| 13 | +DB_USER=admin | |
| 14 | +DB_USER_PASSWORD=basePassw | |
| 15 | +DB_PORT=3306 | |
| 16 | +DB_DRIVER=mysql | |
| 17 | +PRIVATE_API_URL=http://localhost:3000 | |
| 18 | +API_KEY=80dc792592de35b9ac634a8a1f299cf7352e7230d1764b0a42e61b2f3422991d | |
| 19 | +TOKEN_EXPIRATION="30d" | |
| 20 | +TOKEN_SECRET=85712985fdd06085b3032b6d9dba16436f742e4dc650cd66e50bb20373c22f5c | |
| 21 | +CLIENT_SECRET=3d0f23390356bbd818b037863376bad3c7b80da765bb20d9db80d1275f2afd88 | |
| 22 | +PRIVATE_SECRET=6aa003735b66842cd5ad4ac9fa3e069d12e0665a7518e313306f2b7d24ad2f92 | |
| 23 | +RATE_LIMIT_INTERVAL=60000 | |
| 24 | +RATE_LIMIT_REQUEST=10 | |
| 25 | +ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3001 | |
| \ No newline at end of file | ... | ... |
environment/.env.prod
0 → 100644
| 1 | + | |
| 2 | +DATABASE_URL="mysql://root:toor@localhost:3306/base-db" | |
| 3 | + | |
| 4 | +#TESTING DATABASE . CHANGE TO YOUR OWN DATA | |
| 5 | +DB_HOST=base-database | |
| 6 | +DB_ROOT_PASSWORD=toor | |
| 7 | +DB_NAME=base-db | |
| 8 | +DB_USER=admin | |
| 9 | +DB_USER_PASSWORD=basePassw | |
| 10 | +DB_PORT=3306 | |
| 11 | +DB_DRIVER=mysql | |
| 12 | +PRIVATE_API_URL=http://localhost:3000 | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -3,6 +3,27 @@ |
| 3 | 3 | "collection": "@nestjs/schematics", |
| 4 | 4 | "sourceRoot": "src", |
| 5 | 5 | "compilerOptions": { |
| 6 | - "deleteOutDir": true | |
| 6 | + "deleteOutDir": true, | |
| 7 | + "webpack": true | |
| 8 | + }, | |
| 9 | + "projects": { | |
| 10 | + "public": { | |
| 11 | + "type": "library", | |
| 12 | + "root": "libs/public", | |
| 13 | + "entryFile": "index", | |
| 14 | + "sourceRoot": "libs/public/src", | |
| 15 | + "compilerOptions": { | |
| 16 | + "tsConfigPath": "libs/public/tsconfig.lib.json" | |
| 17 | + } | |
| 18 | + }, | |
| 19 | + "private": { | |
| 20 | + "type": "library", | |
| 21 | + "root": "libs/private", | |
| 22 | + "entryFile": "index", | |
| 23 | + "sourceRoot": "libs/private/src", | |
| 24 | + "compilerOptions": { | |
| 25 | + "tsConfigPath": "libs/private/tsconfig.lib.json" | |
| 26 | + } | |
| 27 | + } | |
| 7 | 28 | } |
| 8 | -} | |
| 29 | +} | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -10,12 +10,15 @@ |
| 10 | 10 | "license": "UNLICENSED", |
| 11 | 11 | "dependencies": { |
| 12 | 12 | "@nestjs/common": "^10.2.10", |
| 13 | + "@nestjs/config": "^3.1.1", | |
| 13 | 14 | "@nestjs/core": "^10.0.0", |
| 14 | 15 | "@nestjs/jwt": "^10.2.0", |
| 15 | 16 | "@nestjs/mapped-types": "^2.0.4", |
| 16 | 17 | "@nestjs/passport": "^10.0.2", |
| 17 | 18 | "@nestjs/platform-express": "^10.0.0", |
| 19 | + "@nestjs/throttler": "^5.0.1", | |
| 18 | 20 | "@prisma/client": "^5.6.0", |
| 21 | + "axios": "^1.6.2", | |
| 19 | 22 | "bcrypt": "^5.1.1", |
| 20 | 23 | "cors": "^2.8.5", |
| 21 | 24 | "crypto-js": "^4.2.0", |
| ... | ... | @@ -1709,6 +1712,21 @@ |
| 1709 | 1712 | } |
| 1710 | 1713 | } |
| 1711 | 1714 | }, |
| 1715 | + "node_modules/@nestjs/config": { | |
| 1716 | + "version": "3.1.1", | |
| 1717 | + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz", | |
| 1718 | + "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==", | |
| 1719 | + "dependencies": { | |
| 1720 | + "dotenv": "16.3.1", | |
| 1721 | + "dotenv-expand": "10.0.0", | |
| 1722 | + "lodash": "4.17.21", | |
| 1723 | + "uuid": "9.0.0" | |
| 1724 | + }, | |
| 1725 | + "peerDependencies": { | |
| 1726 | + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", | |
| 1727 | + "reflect-metadata": "^0.1.13" | |
| 1728 | + } | |
| 1729 | + }, | |
| 1712 | 1730 | "node_modules/@nestjs/core": { |
| 1713 | 1731 | "version": "10.2.10", |
| 1714 | 1732 | "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.2.10.tgz", |
| ... | ... | @@ -1849,6 +1867,19 @@ |
| 1849 | 1867 | } |
| 1850 | 1868 | } |
| 1851 | 1869 | }, |
| 1870 | + "node_modules/@nestjs/throttler": { | |
| 1871 | + "version": "5.0.1", | |
| 1872 | + "resolved": "https://registry.npmjs.org/@nestjs/throttler/-/throttler-5.0.1.tgz", | |
| 1873 | + "integrity": "sha512-6gHmKmus7LDgzK/wRh7W9cT3gtZw1rY4mLVymvx6pYyRA46A9fMvjmZNQKJbo02jGg2R7gNo+3pyfvNnjDqg4A==", | |
| 1874 | + "dependencies": { | |
| 1875 | + "md5": "^2.2.1" | |
| 1876 | + }, | |
| 1877 | + "peerDependencies": { | |
| 1878 | + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", | |
| 1879 | + "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", | |
| 1880 | + "reflect-metadata": "^0.1.13" | |
| 1881 | + } | |
| 1882 | + }, | |
| 1852 | 1883 | "node_modules/@nodelib/fs.scandir": { |
| 1853 | 1884 | "version": "2.1.5", |
| 1854 | 1885 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", |
| ... | ... | @@ -2936,8 +2967,17 @@ |
| 2936 | 2967 | "node_modules/asynckit": { |
| 2937 | 2968 | "version": "0.4.0", |
| 2938 | 2969 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", |
| 2939 | - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", | |
| 2940 | - "dev": true | |
| 2970 | + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" | |
| 2971 | + }, | |
| 2972 | + "node_modules/axios": { | |
| 2973 | + "version": "1.6.2", | |
| 2974 | + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", | |
| 2975 | + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", | |
| 2976 | + "dependencies": { | |
| 2977 | + "follow-redirects": "^1.15.0", | |
| 2978 | + "form-data": "^4.0.0", | |
| 2979 | + "proxy-from-env": "^1.1.0" | |
| 2980 | + } | |
| 2941 | 2981 | }, |
| 2942 | 2982 | "node_modules/babel-jest": { |
| 2943 | 2983 | "version": "29.7.0", |
| ... | ... | @@ -3407,6 +3447,14 @@ |
| 3407 | 3447 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", |
| 3408 | 3448 | "dev": true |
| 3409 | 3449 | }, |
| 3450 | + "node_modules/charenc": { | |
| 3451 | + "version": "0.0.2", | |
| 3452 | + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", | |
| 3453 | + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", | |
| 3454 | + "engines": { | |
| 3455 | + "node": "*" | |
| 3456 | + } | |
| 3457 | + }, | |
| 3410 | 3458 | "node_modules/chokidar": { |
| 3411 | 3459 | "version": "3.5.3", |
| 3412 | 3460 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", |
| ... | ... | @@ -3604,7 +3652,6 @@ |
| 3604 | 3652 | "version": "1.0.8", |
| 3605 | 3653 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", |
| 3606 | 3654 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", |
| 3607 | - "dev": true, | |
| 3608 | 3655 | "dependencies": { |
| 3609 | 3656 | "delayed-stream": "~1.0.0" |
| 3610 | 3657 | }, |
| ... | ... | @@ -3803,6 +3850,14 @@ |
| 3803 | 3850 | "node": ">= 8" |
| 3804 | 3851 | } |
| 3805 | 3852 | }, |
| 3853 | + "node_modules/crypt": { | |
| 3854 | + "version": "0.0.2", | |
| 3855 | + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", | |
| 3856 | + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", | |
| 3857 | + "engines": { | |
| 3858 | + "node": "*" | |
| 3859 | + } | |
| 3860 | + }, | |
| 3806 | 3861 | "node_modules/crypto-js": { |
| 3807 | 3862 | "version": "4.2.0", |
| 3808 | 3863 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", |
| ... | ... | @@ -4044,7 +4099,6 @@ |
| 4044 | 4099 | "version": "1.0.0", |
| 4045 | 4100 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", |
| 4046 | 4101 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", |
| 4047 | - "dev": true, | |
| 4048 | 4102 | "engines": { |
| 4049 | 4103 | "node": ">=0.4.0" |
| 4050 | 4104 | } |
| ... | ... | @@ -4140,6 +4194,25 @@ |
| 4140 | 4194 | "node": ">=6.0.0" |
| 4141 | 4195 | } |
| 4142 | 4196 | }, |
| 4197 | + "node_modules/dotenv": { | |
| 4198 | + "version": "16.3.1", | |
| 4199 | + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", | |
| 4200 | + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", | |
| 4201 | + "engines": { | |
| 4202 | + "node": ">=12" | |
| 4203 | + }, | |
| 4204 | + "funding": { | |
| 4205 | + "url": "https://github.com/motdotla/dotenv?sponsor=1" | |
| 4206 | + } | |
| 4207 | + }, | |
| 4208 | + "node_modules/dotenv-expand": { | |
| 4209 | + "version": "10.0.0", | |
| 4210 | + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", | |
| 4211 | + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", | |
| 4212 | + "engines": { | |
| 4213 | + "node": ">=12" | |
| 4214 | + } | |
| 4215 | + }, | |
| 4143 | 4216 | "node_modules/eastasianwidth": { |
| 4144 | 4217 | "version": "0.2.0", |
| 4145 | 4218 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", |
| ... | ... | @@ -4876,6 +4949,25 @@ |
| 4876 | 4949 | "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", |
| 4877 | 4950 | "dev": true |
| 4878 | 4951 | }, |
| 4952 | + "node_modules/follow-redirects": { | |
| 4953 | + "version": "1.15.3", | |
| 4954 | + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", | |
| 4955 | + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", | |
| 4956 | + "funding": [ | |
| 4957 | + { | |
| 4958 | + "type": "individual", | |
| 4959 | + "url": "https://github.com/sponsors/RubenVerborgh" | |
| 4960 | + } | |
| 4961 | + ], | |
| 4962 | + "engines": { | |
| 4963 | + "node": ">=4.0" | |
| 4964 | + }, | |
| 4965 | + "peerDependenciesMeta": { | |
| 4966 | + "debug": { | |
| 4967 | + "optional": true | |
| 4968 | + } | |
| 4969 | + } | |
| 4970 | + }, | |
| 4879 | 4971 | "node_modules/foreground-child": { |
| 4880 | 4972 | "version": "3.1.1", |
| 4881 | 4973 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", |
| ... | ... | @@ -4924,7 +5016,6 @@ |
| 4924 | 5016 | "version": "4.0.0", |
| 4925 | 5017 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", |
| 4926 | 5018 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", |
| 4927 | - "dev": true, | |
| 4928 | 5019 | "dependencies": { |
| 4929 | 5020 | "asynckit": "^0.4.0", |
| 4930 | 5021 | "combined-stream": "^1.0.8", |
| ... | ... | @@ -5514,6 +5605,11 @@ |
| 5514 | 5605 | "node": ">=8" |
| 5515 | 5606 | } |
| 5516 | 5607 | }, |
| 5608 | + "node_modules/is-buffer": { | |
| 5609 | + "version": "1.1.6", | |
| 5610 | + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", | |
| 5611 | + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" | |
| 5612 | + }, | |
| 5517 | 5613 | "node_modules/is-core-module": { |
| 5518 | 5614 | "version": "2.13.1", |
| 5519 | 5615 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", |
| ... | ... | @@ -6598,8 +6694,7 @@ |
| 6598 | 6694 | "node_modules/lodash": { |
| 6599 | 6695 | "version": "4.17.21", |
| 6600 | 6696 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", |
| 6601 | - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", | |
| 6602 | - "dev": true | |
| 6697 | + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" | |
| 6603 | 6698 | }, |
| 6604 | 6699 | "node_modules/lodash.includes": { |
| 6605 | 6700 | "version": "4.3.0", |
| ... | ... | @@ -6727,6 +6822,16 @@ |
| 6727 | 6822 | "tmpl": "1.0.5" |
| 6728 | 6823 | } |
| 6729 | 6824 | }, |
| 6825 | + "node_modules/md5": { | |
| 6826 | + "version": "2.3.0", | |
| 6827 | + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", | |
| 6828 | + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", | |
| 6829 | + "dependencies": { | |
| 6830 | + "charenc": "0.0.2", | |
| 6831 | + "crypt": "0.0.2", | |
| 6832 | + "is-buffer": "~1.1.6" | |
| 6833 | + } | |
| 6834 | + }, | |
| 6730 | 6835 | "node_modules/media-typer": { |
| 6731 | 6836 | "version": "0.3.0", |
| 6732 | 6837 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", |
| ... | ... | @@ -7579,6 +7684,11 @@ |
| 7579 | 7684 | "node": ">= 0.10" |
| 7580 | 7685 | } |
| 7581 | 7686 | }, |
| 7687 | + "node_modules/proxy-from-env": { | |
| 7688 | + "version": "1.1.0", | |
| 7689 | + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", | |
| 7690 | + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" | |
| 7691 | + }, | |
| 7582 | 7692 | "node_modules/pump": { |
| 7583 | 7693 | "version": "3.0.0", |
| 7584 | 7694 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", |
| ... | ... | @@ -9103,6 +9213,14 @@ |
| 9103 | 9213 | "node": ">= 0.4.0" |
| 9104 | 9214 | } |
| 9105 | 9215 | }, |
| 9216 | + "node_modules/uuid": { | |
| 9217 | + "version": "9.0.0", | |
| 9218 | + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", | |
| 9219 | + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", | |
| 9220 | + "bin": { | |
| 9221 | + "uuid": "dist/bin/uuid" | |
| 9222 | + } | |
| 9223 | + }, | |
| 9106 | 9224 | "node_modules/v8-compile-cache-lib": { |
| 9107 | 9225 | "version": "3.0.1", |
| 9108 | 9226 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", | ... | ... |
| ... | ... | @@ -6,12 +6,17 @@ |
| 6 | 6 | "private": true, |
| 7 | 7 | "license": "UNLICENSED", |
| 8 | 8 | "scripts": { |
| 9 | - "build": "nest build", | |
| 10 | - "format": "prettier --write \"src/**/*.ts\"", | |
| 11 | - "start": "nest start", | |
| 12 | - "start:dev": "nest start --watch", | |
| 13 | - "start:debug": "nest start --debug --watch", | |
| 14 | - "start:prod": "node dist/main", | |
| 9 | + "build:prod": "STAGE=prod nest build", | |
| 10 | + "build:dev": "STAGE=dev nest build", | |
| 11 | + "build:local": "STAGE=local nest build", | |
| 12 | + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"", | |
| 13 | + "start": "STAGE=prod nest start", | |
| 14 | + "start:dev": "STAGE=dev nest start --watch", | |
| 15 | + "start:dev:debug": "STAGE=dev nest start --debug --watch", | |
| 16 | + "start:local": "STAGE=local nest start --watch", | |
| 17 | + "start:local:debug": "STAGE=local nest start --debug --watch", | |
| 18 | + "start:prod": "STAGE=prod nest start --watch", | |
| 19 | + "start:prod:debug": "STAGE=prod nest start --debug --watch", | |
| 15 | 20 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", |
| 16 | 21 | "test": "jest", |
| 17 | 22 | "test:watch": "jest --watch", |
| ... | ... | @@ -21,12 +26,15 @@ |
| 21 | 26 | }, |
| 22 | 27 | "dependencies": { |
| 23 | 28 | "@nestjs/common": "^10.2.10", |
| 29 | + "@nestjs/config": "^3.1.1", | |
| 24 | 30 | "@nestjs/core": "^10.0.0", |
| 25 | 31 | "@nestjs/jwt": "^10.2.0", |
| 26 | 32 | "@nestjs/mapped-types": "^2.0.4", |
| 27 | 33 | "@nestjs/passport": "^10.0.2", |
| 28 | 34 | "@nestjs/platform-express": "^10.0.0", |
| 35 | + "@nestjs/throttler": "^5.0.1", | |
| 29 | 36 | "@prisma/client": "^5.6.0", |
| 37 | + "axios": "^1.6.2", | |
| 30 | 38 | "bcrypt": "^5.1.1", |
| 31 | 39 | "cors": "^2.8.5", |
| 32 | 40 | "crypto-js": "^4.2.0", |
| ... | ... | @@ -69,7 +77,7 @@ |
| 69 | 77 | "json", |
| 70 | 78 | "ts" |
| 71 | 79 | ], |
| 72 | - "rootDir": "src", | |
| 80 | + "rootDir": ".", | |
| 73 | 81 | "testRegex": ".*\\.spec\\.ts$", |
| 74 | 82 | "transform": { |
| 75 | 83 | "^.+\\.(t|j)s$": "ts-jest" |
| ... | ... | @@ -77,7 +85,15 @@ |
| 77 | 85 | "collectCoverageFrom": [ |
| 78 | 86 | "**/*.(t|j)s" |
| 79 | 87 | ], |
| 80 | - "coverageDirectory": "../coverage", | |
| 81 | - "testEnvironment": "node" | |
| 88 | + "coverageDirectory": "./coverage", | |
| 89 | + "testEnvironment": "node", | |
| 90 | + "roots": [ | |
| 91 | + "<rootDir>/src/", | |
| 92 | + "<rootDir>/libs/" | |
| 93 | + ], | |
| 94 | + "moduleNameMapper": { | |
| 95 | + "^@app/public(|/.*)$": "<rootDir>/libs/public/src/$1", | |
| 96 | + "^@app/private(|/.*)$": "<rootDir>/libs/private/src/$1" | |
| 97 | + } | |
| 82 | 98 | } |
| 83 | 99 | } | ... | ... |
src/helpers/decryptor.helper.ts
0 → 100644
| 1 | +import { AES, enc } from 'crypto-js'; | |
| 2 | + | |
| 3 | +export const privateDecryptBody = (data: any) => { | |
| 4 | + return JSON.parse(AES.decrypt(data, String(process.env.PRIVATE_SECRET)).toString(enc.Utf8)); | |
| 5 | +}; | |
| 6 | + | |
| 7 | +export const clientDecryptBody = (data: any) => { | |
| 8 | + return JSON.parse(AES.decrypt(data, String(process.env.CLIENT_SECRET)).toString(enc.Utf8)); | |
| 9 | +}; | ... | ... |
| 1 | -const CryptoJS = require('crypto-js'); | |
| 1 | +import { AES } from 'crypto-js'; | |
| 2 | 2 | |
| 3 | -export const encryptBody = (data: any) => { | |
| 4 | - return { | |
| 5 | - data: CryptoJS.AES.encrypt(JSON.stringify(data), 'ditohash').toString() | |
| 6 | - }; | |
| 3 | +export const privateEncryptBody = (data: any) => { | |
| 4 | + const encrypted = AES.encrypt(JSON.stringify(data), String(process.env.PRIVATE_SECRET)).toString(); | |
| 5 | + return { data: encrypted }; | |
| 6 | +}; | |
| 7 | + | |
| 8 | +export const clientEncryptBody = (data: any) => { | |
| 9 | + const encrypted = AES.encrypt(JSON.stringify(data), String(process.env.CLIENT_SECRET)).toString(); | |
| 10 | + return { data: encrypted }; | |
| 7 | 11 | }; | ... | ... |
| ... | ... | @@ -3,6 +3,7 @@ import { AppModule } from './modules/app/app.module'; |
| 3 | 3 | |
| 4 | 4 | async function bootstrap() { |
| 5 | 5 | const app = await NestFactory.create(AppModule); |
| 6 | + app.enableCors({ origin: String(process.env.ALLOWED_ORIGINS).split(',') }); | |
| 6 | 7 | await app.listen(3000); |
| 7 | 8 | } |
| 8 | 9 | bootstrap(); | ... | ... |
| ... | ... | @@ -5,10 +5,26 @@ import { UsersModule } from '../users/users.module'; |
| 5 | 5 | import { PrismaService } from 'src/config/prisma.service'; |
| 6 | 6 | import { AuthModule } from '../auth/auth.module'; |
| 7 | 7 | import { DescryptMiddleware } from './middlewares/decrypt.middleware'; |
| 8 | -// import cors from 'cors'; | |
| 8 | +import { PublicModule } from '@app/public'; | |
| 9 | +import { ConfigModule } from '@nestjs/config'; | |
| 10 | +import { ThrottlerModule } from '@nestjs/throttler'; | |
| 9 | 11 | |
| 10 | 12 | @Module({ |
| 11 | - imports: [UsersModule, AuthModule], | |
| 13 | + imports: [ | |
| 14 | + PublicModule, | |
| 15 | + UsersModule, | |
| 16 | + AuthModule, | |
| 17 | + ConfigModule.forRoot({ | |
| 18 | + isGlobal: true, | |
| 19 | + envFilePath: [`${process.cwd()}/environment/.env.${process.env.STAGE}`], | |
| 20 | + }), | |
| 21 | + ThrottlerModule.forRoot([ | |
| 22 | + { | |
| 23 | + ttl: Number(process.env.RATE_LIMIT_INTERVAL), | |
| 24 | + limit: Number(process.env.RATE_LIMIT_REQUEST), | |
| 25 | + }, | |
| 26 | + ]), | |
| 27 | + ], | |
| 12 | 28 | controllers: [AppController], |
| 13 | 29 | providers: [AppService, PrismaService], |
| 14 | 30 | }) | ... | ... |
| 1 | 1 | import { Injectable, NestMiddleware } from '@nestjs/common'; |
| 2 | +import { JwtService } from '@nestjs/jwt'; | |
| 2 | 3 | import { Request, Response, NextFunction } from 'express'; |
| 3 | -const CryptoJS = require('crypto-js'); | |
| 4 | +import { clientDecryptBody, privateDecryptBody } from 'src/helpers/decryptor.helper'; | |
| 4 | 5 | |
| 5 | 6 | @Injectable() |
| 6 | 7 | export class DescryptMiddleware implements NestMiddleware { |
| 7 | 8 | use(req: Request, res: Response, next: NextFunction) { |
| 8 | - // req.body = (CryptoJS.AES.decrypt(req.body.data, 'ditohash').toString(CryptoJS.enc.Utf8)); | |
| 9 | - console.log( | |
| 10 | - CryptoJS.AES.decrypt(req.body.data, 'ditohash').toString( | |
| 11 | - CryptoJS.enc.Utf8, | |
| 12 | - ), | |
| 13 | - ); | |
| 14 | - next(); | |
| 9 | + const { authorization } = req.headers; | |
| 10 | + | |
| 11 | + if (!authorization) { | |
| 12 | + next(); | |
| 13 | + } | |
| 14 | + | |
| 15 | + const token = authorization?.split(' ')[1] || ''; | |
| 16 | + if (token) { | |
| 17 | + const decodeToken = new JwtService({}).decode(token); | |
| 18 | + if (decodeToken.type === 'public' && !req.baseUrl.includes('/auth/login')) { | |
| 19 | + if (Object.keys(req.body).length !== 0) req.body = clientDecryptBody(req.body.data); | |
| 20 | + } else { | |
| 21 | + if (Object.keys(req.body).length !== 0) req.body = privateDecryptBody(req.body.data); | |
| 22 | + } | |
| 23 | + next(); | |
| 24 | + } | |
| 15 | 25 | } |
| 16 | 26 | } | ... | ... |
| 1 | 1 | import { Controller, Request, Post, UseGuards } from '@nestjs/common'; |
| 2 | 2 | import { AuthService } from './auth.service'; |
| 3 | 3 | import { AuthGuard } from '@nestjs/passport'; |
| 4 | +import { clientEncryptBody, privateEncryptBody } from 'src/helpers/encryptor.helper'; | |
| 5 | +import { ApiKeyGuard } from './guards/api-key.guard'; | |
| 4 | 6 | |
| 5 | 7 | @Controller('auth') |
| 6 | 8 | export class AuthController { |
| 7 | 9 | constructor(private readonly authService: AuthService) { } |
| 8 | 10 | |
| 9 | - // @Post() | |
| 10 | - // create(@Body() createAuthDto: CreateAuthDto) { | |
| 11 | - // return this.authService.create(createAuthDto); | |
| 12 | - // } | |
| 13 | - | |
| 14 | 11 | @UseGuards(AuthGuard('local')) |
| 15 | 12 | @Post('login') |
| 16 | - async login(@Request() req) { | |
| 17 | - return this.authService.login(req.user); | |
| 13 | + async privateLogin(@Request() req) { | |
| 14 | + return privateEncryptBody(await this.authService.privateLogin(req.user)); | |
| 18 | 15 | } |
| 19 | 16 | |
| 20 | - // @Get(':id') | |
| 21 | - // findOne(@Param('id') id: string) { | |
| 22 | - // return this.authService.findOne(+id); | |
| 23 | - // } | |
| 24 | - | |
| 25 | - // @Patch(':id') | |
| 26 | - // update(@Param('id') id: string, @Body() updateAuthDto: UpdateAuthDto) { | |
| 27 | - // return this.authService.update(+id, updateAuthDto); | |
| 28 | - // } | |
| 29 | - | |
| 30 | - // @Delete(':id') | |
| 31 | - // remove(@Param('id') id: string) { | |
| 32 | - // return this.authService.remove(+id); | |
| 33 | - // } | |
| 17 | + @UseGuards(ApiKeyGuard) | |
| 18 | + @Post('public/login') | |
| 19 | + async publicLogin(@Request() req) { | |
| 20 | + return clientEncryptBody(await this.authService.publicLogin()); | |
| 21 | + } | |
| 34 | 22 | } | ... | ... |
| ... | ... | @@ -4,7 +4,7 @@ import { JwtModule } from '@nestjs/jwt'; |
| 4 | 4 | import { jwtConstants } from './misc/constants'; |
| 5 | 5 | import { PassportModule } from '@nestjs/passport'; |
| 6 | 6 | import { LocalStrategy } from './strategies/local.strategy'; |
| 7 | -import { JwtStrategy } from './strategies/jwt.strategy'; | |
| 7 | +import { JwtStrategy } from './strategies/private-jwt.strategy'; | |
| 8 | 8 | import { UsersModule } from '../users/users.module'; |
| 9 | 9 | import { UsersService } from '../users/users.service'; |
| 10 | 10 | import { PrismaService } from 'src/config/prisma.service'; |
| ... | ... | @@ -16,16 +16,10 @@ import { AuthController } from './auth.controller'; |
| 16 | 16 | PassportModule, |
| 17 | 17 | JwtModule.register({ |
| 18 | 18 | secret: jwtConstants.secret, |
| 19 | - signOptions: { expiresIn: '3500s' }, | |
| 19 | + signOptions: { expiresIn: '10d' }, | |
| 20 | 20 | }), |
| 21 | 21 | ], |
| 22 | 22 | controllers: [AuthController], |
| 23 | - providers: [ | |
| 24 | - AuthService, | |
| 25 | - UsersService, | |
| 26 | - PrismaService, | |
| 27 | - LocalStrategy, | |
| 28 | - JwtStrategy, | |
| 29 | - ], | |
| 23 | + providers: [AuthService, UsersService, PrismaService, LocalStrategy, JwtStrategy], | |
| 30 | 24 | }) |
| 31 | 25 | export class AuthModule { } | ... | ... |
| 1 | -import { Injectable, UnauthorizedException } from '@nestjs/common'; | |
| 1 | +import { Injectable } from '@nestjs/common'; | |
| 2 | 2 | import { JwtService } from '@nestjs/jwt'; |
| 3 | 3 | import { UsersService } from '../users/users.service'; |
| 4 | -import * as bcrypt from 'bcrypt' | |
| 4 | +import * as bcrypt from 'bcrypt'; | |
| 5 | 5 | |
| 6 | 6 | @Injectable() |
| 7 | 7 | export class AuthService { |
| ... | ... | @@ -19,10 +19,17 @@ export class AuthService { |
| 19 | 19 | return null; |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | - async login(user: any) { | |
| 23 | - const payload = { username: user.email, sub: user.id }; | |
| 22 | + async publicLogin() { | |
| 23 | + const payload = { type: 'public' }; | |
| 24 | 24 | return { |
| 25 | - access_token: this.jwtService.sign(payload), | |
| 25 | + access_token: this.jwtService.sign(payload, { secret: process.env.TOKEN_SECRET }), | |
| 26 | + }; | |
| 27 | + } | |
| 28 | + | |
| 29 | + async privateLogin(user: any) { | |
| 30 | + const payload = { username: user.email, sub: user.id, type: 'private' }; | |
| 31 | + return { | |
| 32 | + access_token: this.jwtService.sign(payload, { secret: process.env.TOKEN_SECRET }), | |
| 26 | 33 | }; |
| 27 | 34 | } |
| 28 | 35 | } | ... | ... |
src/modules/auth/guards/api-key.guard.ts
0 → 100644
| 1 | +import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common'; | |
| 2 | + | |
| 3 | +@Injectable() | |
| 4 | +export class ApiKeyGuard implements CanActivate { | |
| 5 | + async canActivate(context: ExecutionContext): Promise<boolean> { | |
| 6 | + const request = context.switchToHttp().getRequest(); | |
| 7 | + const apiKey = request.headers['x-api-key']; | |
| 8 | + | |
| 9 | + if (!apiKey) { | |
| 10 | + throw new UnauthorizedException('No API key provided'); | |
| 11 | + } | |
| 12 | + | |
| 13 | + if (apiKey !== process.env.API_KEY) { | |
| 14 | + throw new UnauthorizedException('Invalid API key'); | |
| 15 | + } | |
| 16 | + return true; | |
| 17 | + } | |
| 18 | +} | ... | ... |
src/modules/auth/guards/auth.guard.ts
0 → 100644
| 1 | +import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common'; | |
| 2 | +import { JwtService } from '@nestjs/jwt'; | |
| 3 | +import { Request } from 'express'; | |
| 4 | + | |
| 5 | +@Injectable() | |
| 6 | +export class MixAuthGuard implements CanActivate { | |
| 7 | + constructor( | |
| 8 | + // private jwtService: JwtService, | |
| 9 | + private action, | |
| 10 | + ) { } | |
| 11 | + | |
| 12 | + async canActivate(context: ExecutionContext): Promise<boolean> { | |
| 13 | + const jwtService = new JwtService({}); | |
| 14 | + const request = context.switchToHttp().getRequest(); | |
| 15 | + const token = this.extractTokenFromHeader(request); | |
| 16 | + if (!token) { | |
| 17 | + throw new UnauthorizedException(); | |
| 18 | + } | |
| 19 | + try { | |
| 20 | + await jwtService.verify(token, { secret: process.env.TOKEN_SECRET }); | |
| 21 | + const payload = await jwtService.decode(token); | |
| 22 | + if (payload.type !== this.action) { | |
| 23 | + throw new UnauthorizedException(); | |
| 24 | + } | |
| 25 | + } catch (error: Error | any) { | |
| 26 | + throw new UnauthorizedException(error.message); | |
| 27 | + } | |
| 28 | + return true; | |
| 29 | + } | |
| 30 | + | |
| 31 | + private extractTokenFromHeader(request: Request): string | undefined { | |
| 32 | + const [type, token] = request.headers.authorization?.split(' ') ?? []; | |
| 33 | + return type === 'Bearer' ? token : undefined; | |
| 34 | + } | |
| 35 | +} | |
| \ No newline at end of file | ... | ... |
src/modules/auth/misc/constants 2.ts
deleted
100644 → 0
| ... | ... | @@ -14,6 +14,6 @@ export class JwtStrategy extends PassportStrategy(Strategy) { |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | async validate(payload: any) { |
| 17 | - return { userId: payload.sub, username: payload.username }; | |
| 17 | + return { userId: payload.sub, username: payload.username, type: 'private' }; | |
| 18 | 18 | } |
| 19 | 19 | } | ... | ... |
| 1 | +import { ExtractJwt, Strategy } from 'passport-jwt'; | |
| 2 | +import { PassportStrategy } from '@nestjs/passport'; | |
| 3 | +import { Injectable } from '@nestjs/common'; | |
| 4 | + | |
| 5 | +@Injectable() | |
| 6 | +export class PulbicJwtStrategy extends PassportStrategy(Strategy, 'public') { | |
| 7 | + constructor() { | |
| 8 | + super({ | |
| 9 | + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), | |
| 10 | + ignoreExpiration: false, | |
| 11 | + secretorkley: 'dito-hash-public', | |
| 12 | + }); | |
| 13 | + } | |
| 14 | + | |
| 15 | + async validate() { | |
| 16 | + return { type: 'public' }; | |
| 17 | + } | |
| 18 | +} | ... | ... |
| 1 | -import { | |
| 2 | - Controller, | |
| 3 | - Get, | |
| 4 | - Post, | |
| 5 | - Body, | |
| 6 | - Patch, | |
| 7 | - Param, | |
| 8 | - Delete, | |
| 9 | - UseGuards, | |
| 10 | -} from '@nestjs/common'; | |
| 1 | +import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common'; | |
| 11 | 2 | import { UsersService } from './users.service'; |
| 12 | -import { CreateUserDto } from './dto/create-user.dto'; | |
| 13 | -import { UpdateUserDto } from './dto/update-user.dto'; | |
| 14 | 3 | import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; |
| 15 | -import { encryptBody } from 'src/helpers/encryptor.helper'; | |
| 4 | +import { privateEncryptBody } from 'src/helpers/encryptor.helper'; | |
| 5 | +import { ApiKeyGuard } from '../auth/guards/api-key.guard'; | |
| 6 | +import { MixAuthGuard } from '../auth/guards/auth.guard'; | |
| 16 | 7 | |
| 17 | 8 | @Controller('users') |
| 18 | 9 | export class UsersController { |
| 19 | 10 | constructor(private readonly usersService: UsersService) { } |
| 20 | 11 | |
| 21 | 12 | @Post() |
| 22 | - create(@Body() createUserDto: CreateUserDto) { | |
| 23 | - return this.usersService.create(); | |
| 13 | + create(@Body() createUserDto) { | |
| 14 | + console.log(createUserDto); | |
| 15 | + // return this.usersService.create({ data: createUserDto }); | |
| 24 | 16 | } |
| 25 | 17 | |
| 26 | - @UseGuards(JwtAuthGuard) | |
| 18 | + @UseGuards(ApiKeyGuard, new MixAuthGuard('private')) | |
| 27 | 19 | @Get(':id') |
| 28 | 20 | async findOne(@Param('id') id: string) { |
| 29 | - return encryptBody(this.usersService.findOne(id)); | |
| 21 | + return privateEncryptBody(await this.usersService.findOne(id)); | |
| 30 | 22 | } |
| 31 | 23 | |
| 32 | - @UseGuards(JwtAuthGuard) | |
| 24 | + @UseGuards(ApiKeyGuard, JwtAuthGuard) | |
| 33 | 25 | @Get() |
| 34 | - findAll() { | |
| 35 | - return this.usersService.findAll(); | |
| 26 | + async findAll() { | |
| 27 | + return privateEncryptBody(await this.usersService.findAll()); | |
| 36 | 28 | } |
| 37 | 29 | } | ... | ... |
| ... | ... | @@ -16,6 +16,12 @@ |
| 16 | 16 | "noImplicitAny": false, |
| 17 | 17 | "strictBindCallApply": true, |
| 18 | 18 | "forceConsistentCasingInFileNames": true, |
| 19 | - "noFallthroughCasesInSwitch": true | |
| 19 | + "noFallthroughCasesInSwitch": true, | |
| 20 | + "paths": { | |
| 21 | + "@app/public": ["libs/public-api/src"], | |
| 22 | + "@app/public/*": ["libs/public-api/src/*"], | |
| 23 | + "@app/private": ["libs/private/src"], | |
| 24 | + "@app/private/*": ["libs/private/src/*"] | |
| 25 | + } | |
| 20 | 26 | } |
| 21 | 27 | } | ... | ... |
Please
register
or
login
to post a comment