From 8949c57bdbde45bfc291ca046719d523ee6f1659 Mon Sep 17 00:00:00 2001 From: evenegas Date: Fri, 27 Jun 2025 20:09:46 -0600 Subject: [PATCH] =?UTF-8?q?ultima=20versi=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 328 ++++++++++++++++++++++++++ package.json | 3 + src/auth/auth.service.ts | 4 +- src/mail/mail.controller.ts | 40 +--- src/mail/mail.service.ts | 56 ++++- src/sistema/dto/create-sistema.dto.ts | 11 + src/sistema/sistema.service.ts | 15 +- src/typeorm/entidades.ts | 23 +- 8 files changed, 435 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a5d240..37a0e28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "license": "UNLICENSED", "dependencies": { + "@nestjs/bull": "^11.0.2", "@nestjs/common": "^11.0.1", "@nestjs/config": "^4.0.1", "@nestjs/core": "^11.0.1", @@ -17,6 +18,7 @@ "@nestjs/platform-express": "^11.0.1", "@nestjs/swagger": "^11.0.5", "@nestjs/typeorm": "^11.0.0", + "bull": "^4.16.5", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "csv-parser": "^3.2.0", @@ -39,6 +41,7 @@ "@nestjs/testing": "^11.0.1", "@swc/cli": "^0.6.0", "@swc/core": "^1.10.7", + "@types/bull": "^3.15.9", "@types/express": "^5.0.0", "@types/jest": "^29.5.14", "@types/multer": "^1.4.12", @@ -1253,6 +1256,12 @@ } } }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "license": "MIT" + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1837,6 +1846,84 @@ "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz", "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==" }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@napi-rs/nice": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.1.tgz", @@ -2125,6 +2212,34 @@ "node": ">= 10" } }, + "node_modules/@nestjs/bull": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-11.0.2.tgz", + "integrity": "sha512-RjyP9JZUuLmMhmq1TMNIZqolkAd14az1jyXMMVki+C9dYvaMjWzBSwcZAtKs9Pk15Rm7qN1xn3R11aMV2Xv4gg==", + "license": "MIT", + "dependencies": { + "@nestjs/bull-shared": "^11.0.2", + "tslib": "2.8.1" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", + "bull": "^3.3 || ^4.0.0" + } + }, + "node_modules/@nestjs/bull-shared": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.2.tgz", + "integrity": "sha512-dFlttJvBqIFD6M8JVFbkrR4Feb39OTAJPJpFVILU50NOJCM4qziRw3dSNG84Q3v+7/M6xUGMFdZRRGvBBKxoSA==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0" + } + }, "node_modules/@nestjs/cli": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-11.0.5.tgz", @@ -3065,6 +3180,17 @@ "@types/node": "*" } }, + "node_modules/@types/bull": { + "version": "3.15.9", + "resolved": "https://registry.npmjs.org/@types/bull/-/bull-3.15.9.tgz", + "integrity": "sha512-MPUcyPPQauAmynoO3ezHAmCOhbB0pWmYyijr/5ctaCqhbKWsjW0YCod38ZcLzUBprosfZ9dPqfYIcfdKjk7RNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ioredis": "*", + "@types/redis": "^2.8.0" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -3151,6 +3277,16 @@ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true }, + "node_modules/@types/ioredis": { + "version": "4.28.10", + "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", + "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -3241,6 +3377,16 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, + "node_modules/@types/redis": { + "version": "2.8.32", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.32.tgz", + "integrity": "sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -4588,6 +4734,33 @@ "node": ">=0.2.0" } }, + "node_modules/bull": { + "version": "4.16.5", + "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.5.tgz", + "integrity": "sha512-lDsx2BzkKe7gkCYiT5Acj02DpTwDznl/VNN7Psn7M3USPG7Vs/BaClZJJTAG+ufAR9++N1/NiUTdaFBWDIl5TQ==", + "license": "MIT", + "dependencies": { + "cron-parser": "^4.9.0", + "get-port": "^5.1.1", + "ioredis": "^5.3.2", + "lodash": "^4.17.21", + "msgpackr": "^1.11.2", + "semver": "^7.5.2", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/bull/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -4908,6 +5081,15 @@ "node": ">=0.8" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5194,6 +5376,18 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "devOptional": true }, + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "license": "MIT", + "dependencies": { + "luxon": "^3.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -5350,6 +5544,16 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -6687,6 +6891,18 @@ "node": ">=8.0.0" } }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -7051,6 +7267,30 @@ "kind-of": "^6.0.2" } }, + "node_modules/ioredis": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz", + "integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -8246,6 +8486,12 @@ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", "license": "MIT" }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", @@ -8379,6 +8625,15 @@ "url": "https://github.com/sponsors/wellwelwel" } }, + "node_modules/luxon": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.6.1.tgz", + "integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -8600,6 +8855,37 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/msgpackr": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz", + "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, "node_modules/multer": { "version": "1.4.5-lts.1", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", @@ -8749,6 +9035,21 @@ "lodash": "^4.17.21" } }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -9522,6 +9823,27 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/reflect-metadata": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", @@ -10165,6 +10487,12 @@ "node": ">=8" } }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", diff --git a/package.json b/package.json index e31b58b..4853db4 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { + "@nestjs/bull": "^11.0.2", "@nestjs/common": "^11.0.1", "@nestjs/config": "^4.0.1", "@nestjs/core": "^11.0.1", @@ -28,6 +29,7 @@ "@nestjs/platform-express": "^11.0.1", "@nestjs/swagger": "^11.0.5", "@nestjs/typeorm": "^11.0.0", + "bull": "^4.16.5", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "csv-parser": "^3.2.0", @@ -50,6 +52,7 @@ "@nestjs/testing": "^11.0.1", "@swc/cli": "^0.6.0", "@swc/core": "^1.10.7", + "@types/bull": "^3.15.9", "@types/express": "^5.0.0", "@types/jest": "^29.5.14", "@types/multer": "^1.4.12", diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 314c4d9..64290f7 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -7,7 +7,7 @@ export class AuthService { generarToken(payload: any) { return this.jwtService.sign(payload, { - secret: process.env.JWT_SECRET, // <-- Aquí lo defines explícitamente + secret: process.env.JWT_SECRET, expiresIn: '1d', }); } @@ -15,7 +15,7 @@ export class AuthService { verificarToken(token: string) { try { return this.jwtService.verify(token, { - secret: process.env.JWT_SECRET, // <-- También aquí + secret: process.env.JWT_SECRET, }); } catch { return null; diff --git a/src/mail/mail.controller.ts b/src/mail/mail.controller.ts index 68ab6a0..59ac43a 100644 --- a/src/mail/mail.controller.ts +++ b/src/mail/mail.controller.ts @@ -2,23 +2,14 @@ import { Controller, Post, Body, - UploadedFile, Headers, UnauthorizedException, - Get, - UseInterceptors, } from '@nestjs/common'; import { MailService } from './mail.service'; -import { ExcelService } from 'src/excel/excel.service'; import { ApiTags } from '@nestjs/swagger'; import { ApiSendMail} from './mail.decorators'; -import { Repository } from 'typeorm'; -import { Sistema } from 'src/typeorm/entidades'; -import { InjectRepository } from '@nestjs/typeorm'; import { SistemaService } from 'src/sistema/sistema.service'; -import { JwtService } from '@nestjs/jwt'; import { SendCorreoDto } from 'src/mail/dto/send-email.dto'; -import { FileInterceptor } from '@nestjs/platform-express'; import { AuthService } from 'src/auth/auth.service'; @@ -47,26 +38,19 @@ export class MailController { if (!headers.token) { throw new UnauthorizedException('Header "token" es requerido'); } - let payload - - payload = await this.authService.verificarToken(headers.token); - - - if (!payload || !payload.nombre) { - throw new UnauthorizedException('Token inválido o incompleto'); - } - - const sistem= await this.sistemaService.findByNombre(payload.nombre) - - - if(!sistem){ - throw new UnauthorizedException('sistema No encontrado'); - } - - - - const result = await this.mailService.sendMail(body,sistem); // sistem + const result = + await this.mailService.sendMail(body,headers.token) + .then((value) => { + console.log("ya acabe el correo", value); + + }) + .catch((err)=>{ + console.log(err) + }) + + + // sistem return result; diff --git a/src/mail/mail.service.ts b/src/mail/mail.service.ts index f70a3fa..be98d09 100644 --- a/src/mail/mail.service.ts +++ b/src/mail/mail.service.ts @@ -1,6 +1,5 @@ import { Injectable, UnauthorizedException } from '@nestjs/common'; import * as nodemailer from 'nodemailer'; -import * as dotenv from 'dotenv'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Correo, Sistema, Status } from '../typeorm/entidades'; @@ -13,7 +12,7 @@ import { decrypt } from '../crypto/crypto.util'; @Injectable() export class MailService { - private transporter; + constructor( private readonly sistemaService: SistemaService, @@ -91,10 +90,25 @@ export class MailService { },} ) return result - } +} - async sendMail(sendEmail:SendCorreoDto,sistem:Sistema,) { +async sendMail(sendEmail:SendCorreoDto,token:string) { + + let payload + + payload = await this.authService.verificarToken(token); + + if (!payload || !payload.nombre) { + throw new UnauthorizedException('Token inválido o incompleto'); + } + + const sistem= await this.sistemaService.findByNombre(payload.nombre) + + + if(!sistem){ + throw new UnauthorizedException('sistema No encontrado'); + } @@ -104,10 +118,17 @@ export class MailService { sistem.email_password_iv ); + const decryptedToken = decrypt( + sistem.refreshToken_encrypted, + sistem.refreshToken_iv + ); + + + const transporter = nodemailer.createTransport({ - host: 'smtp.gmail.com', // o smtp‑relay.gmail.com (ver punto 2) + /* host: 'smtp.gmail.com', // o smtp‑relay.gmail.com (ver punto 2) port: 587, secure: false, requireTLS: true, // TLS STARTTLS @@ -117,6 +138,24 @@ export class MailService { maxMessages: 100, // reabrir después de 100 envíos rateDelta: 2000, // ventana 1 s rateLimit: 1 // máx. 5 mensajes/seg + */ + + service: 'gmail', + auth: { + type: 'OAuth2', + user: sistem.email, + clientId: sistem.clientId, + clientSecret: decryptedPassword, + refreshToken: decryptedToken, + //accessToken: sistem.accessToken, // opcional + }, + pool: true, + maxConnections: 1, + maxMessages: 100, + rateDelta: 2000, + rateLimit: 1 + + }); @@ -159,6 +198,9 @@ export class MailService { let resMail = await transporter.sendMail(mailOptions); +if(!resMail) throw new Error("") + + const statusTexto = resMail.accepted.length > 0 ? "Enviado" : "Fallido"; @@ -176,11 +218,11 @@ export class MailService { fecha_recibido: sendEmail.fecha_recibido, fecha_enviado: new Date(), destinatario: sendEmail.to, - remitente: process.env.USER_GMAIL, + remitente: sistem.email, }); - + if(!resMail){ throw new Error("fallo") } diff --git a/src/sistema/dto/create-sistema.dto.ts b/src/sistema/dto/create-sistema.dto.ts index 8e2e8df..189b965 100644 --- a/src/sistema/dto/create-sistema.dto.ts +++ b/src/sistema/dto/create-sistema.dto.ts @@ -9,6 +9,7 @@ export class CreateSistemaDto { @IsString() ip:string; + //Password del sistema @IsNotEmpty() @IsString() password: string; @@ -17,10 +18,20 @@ export class CreateSistemaDto { @IsString() email: string; + //clientSecret @IsNotEmpty() @IsString() email_password:string + @IsNotEmpty() + @IsString() + clientId:string + + //TU_REFRESH_TOKEN + @IsNotEmpty() + @IsString() + refreshToken:string; + } diff --git a/src/sistema/sistema.service.ts b/src/sistema/sistema.service.ts index a5f4108..603ff23 100644 --- a/src/sistema/sistema.service.ts +++ b/src/sistema/sistema.service.ts @@ -46,14 +46,23 @@ export class SistemaService { throw new UnauthorizedException('Password erróneo'); } - const { encryptedData, iv } = encrypt(createSistemaDto.email_password); + const {encryptedData:encryptedData_token,iv:encryptedData_iv}= encrypt(createSistemaDto.refreshToken) + + const { encryptedData:encrypted_password, iv:iv_password } = encrypt(createSistemaDto.email_password); const sistema = this.sistemaRepository.create({ nombre_sistema: createSistemaDto.Nombre, ip: createSistemaDto.ip, email:createSistemaDto.email, - email_password_encrypted: encryptedData, - email_password_iv: iv + email_password_encrypted: encrypted_password, + email_password_iv: iv_password, + clientId: createSistemaDto.clientId, + refreshToken_encrypted:encryptedData_token, + refreshToken_iv: encryptedData_iv + + + + }); await this.sistemaRepository.save(sistema); diff --git a/src/typeorm/entidades.ts b/src/typeorm/entidades.ts index 6e51337..7d7bc2d 100644 --- a/src/typeorm/entidades.ts +++ b/src/typeorm/entidades.ts @@ -6,21 +6,34 @@ export class Sistema { @PrimaryGeneratedColumn() id_sistema: number; - @Column({ type: 'varchar', length: 50 }) + @Column({ type: 'varchar', length: 50, nullable: false }) nombre_sistema: string; - @Column({ type: 'varchar', length: 50 }) + @Column({ type: 'varchar', length: 50,nullable: false }) ip:string; - @Column() + @Column({nullable: false}) email: string; - @Column() + //clientSecret encriptada + @Column({nullable: false}) email_password_encrypted: string; + - @Column() + @Column({nullable: false}) email_password_iv: string; + @Column({nullable: false}) + clientId:string + + //TU_REFRESH_TOKEN + @Column({nullable: false}) + refreshToken_encrypted:string; + + @Column({nullable: false}) + refreshToken_iv: string; + + @OneToMany(() => Correo, (correo) => correo.id_sistema) correos: Correo[]; }