This commit is contained in:
David Arranz 2025-02-05 21:40:59 +01:00
parent 8ead5a62da
commit 36788f34e8
34 changed files with 258 additions and 2122 deletions

View File

@ -6,14 +6,9 @@
"auditLog": ".571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json",
"files": [
{
"date": 1738578708264,
"name": "debug-2025-02-03.log",
"hash": "48ca17f819e391cb5ae1909a6ee0fa4d9c8cdb6667ef893547acb004f4a79737"
},
{
"date": 1738664864746,
"name": "debug-2025-02-04.log",
"hash": "7f1ecce0e9a97fbb99865ac9bfc3591897975a2fd9562164c9be52aabc47f47f"
"date": 1738768744297,
"name": "debug-2025-02-05.log",
"hash": "35182b14bda063a4b734238473f84cfa66a0362a76d8f12f0c20277df81c7256"
}
],
"hashType": "sha256"

View File

@ -6,14 +6,9 @@
"auditLog": ".e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json",
"files": [
{
"date": 1738578708262,
"name": "error-2025-02-03.log",
"hash": "a21f154f5c386a75eee98a35c2b100da7df1b8002cf99851b90bd12810f1fe8a"
},
{
"date": 1738664864743,
"name": "error-2025-02-04.log",
"hash": "dfb19c1e5b9c2039572425939e77f4d4ab3285df0fcded1edfba3e7c4cc2a94d"
"date": 1738768744292,
"name": "error-2025-02-05.log",
"hash": "c32d976d68382b2ba2ddec8c907c30547ec9fda2bb31180bfdbeb685964810a8"
}
],
"hashType": "sha256"

File diff suppressed because it is too large Load Diff

View File

@ -1,86 +0,0 @@
{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:31:54 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:31:54.031Z"}
{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:31:54.034Z"}
{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:33:04 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:33:04.894Z"}
{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:33:04.896Z"}
{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:33:49 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:33:49.232Z"}
{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:33:49.233Z"}
{"label":"index.ts","level":"error","message":"Mon, 03 Feb 2025 10:37:14 GMT uncaughtException:","metadata":{"0":"S","1":"e","10":"n","11":"o","12":"t","13":" ","14":"r","15":"u","16":"n","17":"n","18":"i","19":"n","2":"r","20":"g","21":".","3":"v","4":"e","5":"r","6":" ","7":"i","8":"s","9":" "},"timestamp":"2025-02-03T10:37:14.756Z"}
{"label":"index.ts","level":"error","message":"Error [ERR_SERVER_NOT_RUNNING]: Server is not running.\n at Server.close (node:net:2356:12)\n at Object.onceWrapper (node:events:638:28)\n at Server.emit (node:events:536:35)\n at emitCloseNT (node:net:2416:8)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)","metadata":{},"timestamp":"2025-02-03T10:37:14.758Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:47:26.394Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:47:46.769Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T10:56:00.612Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","name":"SequelizeDatabaseError","original":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"parameters":{},"parent":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');"},"timestamp":"2025-02-03T11:08:06.568Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","name":"SequelizeDatabaseError","original":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"parameters":{},"parent":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');"},"timestamp":"2025-02-03T11:08:30.574Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","code":"ERR_SERVER_NOT_RUNNING"},"timestamp":"2025-02-03T11:09:05.310Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","name":"SequelizeDatabaseError","original":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"parameters":{},"parent":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');"},"timestamp":"2025-02-03T11:14:03.193Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","name":"SequelizeDatabaseError","original":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"parameters":{},"parent":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');"},"timestamp":"2025-02-03T11:20:47.049Z"}
{"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:21:20.528Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","name":"SequelizeDatabaseError","original":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"parameters":{},"parent":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');"},"timestamp":"2025-02-03T11:22:22.098Z"}
{"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:29:22.891Z"}
{"label":"index.ts","level":"error","message":"Could not close connections in time, forcefully shutting down","metadata":{},"timestamp":"2025-02-03T11:30:14.987Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":","name":"SequelizeDatabaseError","original":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"parameters":{},"parent":{"code":"ER_NO_SUCH_TABLE","errno":1146,"fatal":false,"name":"SqlError","sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');","sqlMessage":"Table 'uecko_erp.users' doesn't exist","sqlState":"42S02"},"sql":"SELECT `id`, `username`, `email`, `password`, `roles`, `isActive`, `created_at`, `updated_at`, `deleted_at` FROM `users` AS `AuthUserModel` WHERE (`AuthUserModel`.`deleted_at` IS NULL AND `AuthUserModel`.`id` = 'email');"},"timestamp":"2025-02-03T11:39:04.414Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T13:05:42.332Z"}
{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:05.262Z"}
{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:05.277Z"}
{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:35.470Z"}
{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:35.473Z"}
{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T15:59:48.809Z"}
{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T15:59:48.811Z"}
{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T16:01:28.918Z"}
{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:01:28.932Z"}
{"label":"index.ts","level":"error","message":"Database error: value.join is not a function","metadata":{},"timestamp":"2025-02-03T16:02:07.671Z"}
{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:02:07.678Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:05:54.782Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:06:09.336Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:06:09.345Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:22.183Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:29:22.193Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:25.843Z"}
{"label":"index.ts","level":"error","message":"[500] Internal Server Error: Unexpected database error","metadata":{},"timestamp":"2025-02-03T16:29:25.848Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:29:58.465Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:29:58.471Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:30:58.651Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:30:58.659Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:31:11.297Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:31:39.443Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:31:39.446Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:42:21.737Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T16:53:04.645Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T16:53:04.652Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:53:24.919Z"}
{"label":"index.ts","level":"error","message":"Unhandled Rejection at:","metadata":{"0":"r","1":"e","2":"a","3":"s","4":"o","5":"n","6":":"},"timestamp":"2025-02-03T16:53:59.783Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T17:53:46.420Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T17:53:46.434Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Validation Error","metadata":{},"timestamp":"2025-02-03T18:09:57.217Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Validation Error","metadata":{},"timestamp":"2025-02-03T18:10:42.558Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T18:34:31.991Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T18:36:02.667Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T18:44:04.627Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T18:44:24.719Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T18:46:29.064Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T18:46:40.967Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T19:07:24.350Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T19:07:24.352Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"local-jwt\"","metadata":{},"timestamp":"2025-02-03T19:09:15.070Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T19:09:23.879Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:635, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:50:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:42:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:109:5"},"timestamp":"2025-02-03T19:24:23.645Z"}
{"label":"index.ts","level":"error","message":"Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T19:45:07.427Z"}
{"label":"index.ts","level":"error","message":"💥 Unhandled API error: Unknown authentication strategy \"jwt\"","metadata":{},"timestamp":"2025-02-03T19:46:17.959Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:823, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:42:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:43:21.049Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:827, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:42:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:43:23.751Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:829, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:42:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:43:37.528Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:833, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:42:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:43:44.126Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:835, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:42:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:44:09.809Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:839, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:42:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:46:33.069Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:842, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:43:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:46:50.035Z"}
{"label":"index.ts","level":"error","message":"❌ Error synchronizing database: (conn:845, no: 1069, SQLState: 42000) Too many keys specified; max 64 keys allowed\nsql: ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE; - parameters:[]","metadata":{"name":"SequelizeDatabaseError","original":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"parameters":{},"parent":{"code":"ER_TOO_MANY_KEYS","errno":1069,"fatal":false,"name":"SqlError","sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","sqlMessage":"Too many keys specified; max 64 keys allowed","sqlState":"42000"},"sql":"ALTER TABLE `users` CHANGE `email` `email` VARCHAR(255) NOT NULL UNIQUE;","stack":"Error: \n at Query.run (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/dialects/mariadb/query.js:47:25)\n at /home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:650:28\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at Function.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/model.js:1408:11)\n at Sequelize.sync (/home/rodax/Documentos/uecko-erp/node_modules/.pnpm/sequelize@6.37.5_mariadb@3.4.0_mysql2@3.12.0/node_modules/sequelize/src/sequelize.js:825:9)\n at registerModels (/home/rodax/Documentos/uecko-erp/apps/server/src/config/register-models.ts:57:7)\n at connectToDatabase (/home/rodax/Documentos/uecko-erp/apps/server/src/config/database.ts:43:5)\n at /home/rodax/Documentos/uecko-erp/apps/server/src/index.ts:115:5"},"timestamp":"2025-02-03T21:47:08.690Z"}
{"label":"index.ts","level":"error","message":"❌ Unhandled API error: createLoginController is not defined","metadata":{},"timestamp":"2025-02-03T21:50:39.274Z"}
{"label":"index.ts","level":"error","message":"❌ Unhandled API error: createLoginController is not defined","metadata":{},"timestamp":"2025-02-03T21:52:51.178Z"}
{"label":"index.ts","level":"error","message":"❌ Unhandled API error: createLoginController is not defined","metadata":{},"timestamp":"2025-02-03T21:53:12.086Z"}
{"label":"index.ts","level":"error","message":"[503] Service Unavailable: Invalid email or password","metadata":{},"timestamp":"2025-02-03T21:53:25.527Z"}
{"label":"index.ts","level":"error","message":"[503] Service Unavailable: Invalid email or password","metadata":{},"timestamp":"2025-02-03T21:53:36.301Z"}
{"label":"index.ts","level":"error","message":"[503] Service Unavailable: Invalid email or password","metadata":{},"timestamp":"2025-02-03T21:53:39.351Z"}
{"label":"index.ts","level":"error","message":"[401] Unauthorized: Invalid email or password","metadata":{},"timestamp":"2025-02-03T21:53:53.504Z"}
{"label":"index.ts","level":"error","message":"Database error: Validation error","metadata":{},"timestamp":"2025-02-03T21:54:31.584Z"}
{"label":"index.ts","level":"error","message":"[409] Conflict: User with this email already exists","metadata":{},"timestamp":"2025-02-03T21:54:31.587Z"}
{"label":"index.ts","level":"error","message":"[401] Unauthorized: Invalid email or password","metadata":{},"timestamp":"2025-02-03T21:54:42.181Z"}

View File

@ -1,5 +1,6 @@
import { logger } from "@common/infrastructure/logger";
import { globalErrorHandler } from "@common/presentation";
import { initializePassportAuthProvide } from "@contexts/auth/infraestructure";
import dotenv from "dotenv";
import express, { Application } from "express";
import helmet from "helmet";
@ -24,7 +25,10 @@ export function createApp(): Application {
app.use(responseTime()); // set up the response-time middleware
// Inicializar Passport
//app.use((req, res, next) => createPassportAuthProvider());
app.use((req, res, next) => {
initializePassportAuthProvide();
next();
});
app.use((req, _, next) => {
logger.info(`▶️ Incoming request ${req.method} to ${req.path}`);

View File

@ -109,8 +109,9 @@ export abstract class ExpressController {
return ExpressController.errorResponse(
new ApiError({
status: 422,
title: "Invalid Input",
detail: message,
title: httpStatus["422"],
name: httpStatus["422_NAME"],
detail: message ?? httpStatus["422_MESSAGE"],
errors,
}),
this.res

View File

@ -2,10 +2,10 @@ import { AuthenticatedUser } from "../domain";
export interface IAuthProvider {
/* JWT Strategy */
generateAccessToken(payload: any): string;
generateRefreshToken(payload: any): string;
verifyToken(token: string): any;
generateAccessToken(payload: object): string;
generateRefreshToken(payload: object): string;
verifyToken(token: string): Promise<AuthenticatedUser | null>;
/* LocalStrategy */
verifyUser(email: string, password: string): Promise<AuthenticatedUser | null>;
//_verifyUser(email: string, password: string): Promise<AuthenticatedUser | null>;
}

View File

@ -1,14 +1,18 @@
import { Result, UniqueID } from "@common/domain";
import { AuthenticatedUser, EmailAddress, PasswordHash, Username } from "../domain";
import { AuthenticatedUser, EmailAddress, HashPassword, PlainPassword, Username } from "../domain";
export interface IAuthService {
registerUser(params: {
username: Username;
email: EmailAddress;
passwordHash: PasswordHash;
hashPassword: HashPassword;
}): Promise<Result<AuthenticatedUser, Error>>;
loginUser(params: { email: EmailAddress; passwordHash: PasswordHash; tabId: UniqueID }): Promise<
loginUser(params: {
email: EmailAddress;
plainPassword: PlainPassword;
tabId: UniqueID;
}): Promise<
Result<
{
user: AuthenticatedUser;

View File

@ -3,8 +3,8 @@ import { ITransactionManager } from "@common/infrastructure/database";
import {
AuthenticatedUser,
EmailAddress,
HashPassword,
IAuthenticatedUserRepository,
PasswordHash,
TabContext,
Username,
} from "../domain";
@ -37,29 +37,25 @@ export class AuthService implements IAuthService {
async registerUser(params: {
username: Username;
email: EmailAddress;
passwordHash: PasswordHash;
hashPassword: HashPassword;
}): Promise<Result<AuthenticatedUser, Error>> {
try {
return await this._transactionManager.complete(async (transaction) => {
const { username, email, passwordHash } = params;
const { username, email, hashPassword } = params;
// Verificar si el usuario ya existe
const userExists = await this._userRepo.findUserByEmail(email, transaction);
const userExists = await this._userRepo.userExists(email, transaction);
if (userExists.isSuccess && userExists.data) {
return Result.fail(new Error("Email is already registered"));
}
if (userExists.isFailure) {
return Result.fail(userExists.error);
}
const newUserId = UniqueID.generateNewID().data;
const userOrError = AuthenticatedUser.create(
{
username,
email,
passwordHash,
hashPassword,
roles: ["USER"],
},
newUserId
@ -88,7 +84,7 @@ export class AuthService implements IAuthService {
*/
async loginUser(params: {
email: EmailAddress;
passwordHash: PasswordHash;
plainPassword: HashPassword;
tabId: UniqueID;
}): Promise<
Result<
@ -104,7 +100,7 @@ export class AuthService implements IAuthService {
> {
try {
return await this._transactionManager.complete(async (transaction) => {
const { email, passwordHash, tabId } = params;
const { email, plainPassword, tabId } = params;
// Verificar que el tab ID está definido
if (!tabId.isDefined()) {
@ -112,7 +108,7 @@ export class AuthService implements IAuthService {
}
// 🔹 Verificar si el usuario existe en la base de datos
const userResult = await this._userRepo.findUserByEmail(email, transaction);
const userResult = await this._userRepo.getUserByEmail(email, transaction);
if (userResult.isFailure) {
return Result.fail(new Error("Invalid email or password"));
}
@ -120,7 +116,7 @@ export class AuthService implements IAuthService {
const user = userResult.data;
// 🔹 Verificar que la contraseña sea correcta
const isValidPassword = await user.comparePassword(passwordHash);
const isValidPassword = await user.verifyPassword(plainPassword);
if (!isValidPassword) {
return Result.fail(new Error("Invalid email or password"));
}

View File

@ -5,6 +5,8 @@ import { createPassportAuthProvider } from "../infraestructure/passport/passport
import { IAuthProvider } from "./auth-provider.interface";
import { IAuthService } from "./auth-service.interface";
import { AuthService } from "./auth.service";
import { ITabContextService } from "./tab-context-service.interface";
import { TabContextService } from "./tab-context.service";
export * from "./auth-provider.interface";
export * from "./auth-service.interface";
@ -25,3 +27,10 @@ export const createAuthService = (): IAuthService => {
authProvider
);
};
export const createTabContextService = (): ITabContextService => {
const transactionManager = createSequelizeTransactionManager();
const tabContextRepository = createTabContextRepository();
return new TabContextService(tabContextRepository, transactionManager);
};

View File

@ -2,7 +2,7 @@ import { Result, UniqueID } from "@common/domain";
import { TabContext } from "../domain";
export interface ITabContextService {
getByTabId(tabId: UniqueID): Promise<Result<TabContext, Error>>;
getContextByTabId(tabId: UniqueID): Promise<Result<TabContext, Error>>;
createContext(params: {
tabId: UniqueID;
userId: UniqueID;

View File

@ -16,7 +16,7 @@ export class TabContextService implements ITabContextService {
/**
* Obtiene el contexto de una pestaña por su ID
*/
async getByTabId(tabId: UniqueID): Promise<Result<TabContext, Error>> {
async getContextByTabId(tabId: UniqueID): Promise<Result<TabContext, Error>> {
try {
return await this._transactionManager.complete(async (transaction) => {
// Verificar si la pestaña existe

View File

@ -1,11 +1,11 @@
import { AggregateRoot, Result, UniqueID } from "@common/domain";
import { UserAuthenticatedEvent } from "../events";
import { EmailAddress, PasswordHash, Username } from "../value-objects";
import { EmailAddress, HashPassword, PlainPassword, Username } from "../value-objects";
export interface IAuthenticatedUserProps {
username: Username;
email: EmailAddress;
passwordHash: PasswordHash;
hashPassword: HashPassword;
roles: string[];
}
@ -19,7 +19,9 @@ export interface IAuthenticatedUser {
isUser: boolean;
isAdmin: boolean;
comparePassword(password: PasswordHash | string): Promise<boolean>;
contexts: ICollection<QuoteItem>;
verifyPassword(candidatePassword: PlainPassword): Promise<boolean>;
getRoles(): string[];
toPersistenceData(): any;
}
@ -45,12 +47,8 @@ export class AuthenticatedUser
return (this._props.roles || []).some((r) => r === role);
}
comparePassword(password: PasswordHash | string): Promise<boolean> {
if (typeof password === "string") {
return this._props.passwordHash.compare(password);
} else {
return this._props.passwordHash.compare(password.toString());
}
verifyPassword(candidatePassword: PlainPassword): Promise<boolean> {
return this._props.hashPassword.verifyPassword(candidatePassword.toString());
}
getRoles(): string[] {
@ -81,10 +79,10 @@ export class AuthenticatedUser
id: this._id.toString(),
username: this._props.username.toString(),
email: this._props.email.toString(),
password: this._props.passwordHash.toString(),
hash_password: this._props.hashPassword.toString(),
roles: this._props.roles.map((role) => role.toString()),
accessToken: this.accessToken,
refreshToken: this.refreshToken,
access_token: this.accessToken,
refresh_token: this.refreshToken,
};
}
}

View File

@ -54,9 +54,10 @@ export class TabContext extends DomainEntity<ITabContextProps> implements ITabCo
toPersistenceData(): any {
return {
id: this._id.toString(),
tab_id: this.tabId.toString(),
user_id: this.userId.toString(),
company_id: this.companyId.toString(),
branchId: this.branchId.toString(),
branch_id: this.branchId.toString(),
};
}
}

View File

@ -3,10 +3,7 @@ import { AuthenticatedUser } from "../aggregates";
import { EmailAddress } from "../value-objects";
export interface IAuthenticatedUserRepository {
findUserByEmail(
email: EmailAddress,
transaction?: any
): Promise<Result<AuthenticatedUser, Error>>;
getUserByEmail(email: EmailAddress, transaction?: any): Promise<Result<AuthenticatedUser, Error>>;
userExists(email: EmailAddress, transaction?: any): Promise<Result<boolean, Error>>;
createUser(user: AuthenticatedUser, transaction?: any): Promise<Result<void, Error>>;
}

View File

@ -1,33 +1,33 @@
import { PasswordHash } from "./password-hash";
import { HashPassword } from "./hash-password";
describe("PasswordHash Value Object", () => {
it("should hash a valid password", async () => {
const result = await PasswordHash.create("StrongPass123");
const result = HashPassword.create("StrongPass123");
expect(result.isSuccess).toBe(true);
expect(result.data.getValue()).not.toBe("StrongPass123"); // Should be hashed
});
it("should return an error for short password", async () => {
const result = await PasswordHash.create("12345");
const result = HashPassword.create("12345");
expect(result.isSuccess).toBe(true);
expect(result.error.message).toBe("Password must be at least 6 characters long");
});
it("should validate password comparison correctly", async () => {
const result = await PasswordHash.create("SecurePass123");
const result = HashPassword.create("SecurePass123");
expect(result.isSuccess).toBe(true);
const isValid = await result.data.compare("SecurePass123");
const isValid = await result.data.verifyPassword("SecurePass123");
expect(isValid).toBe(true);
});
it("should fail password comparison for incorrect passwords", async () => {
const result = await PasswordHash.create("SecurePass123");
const result = HashPassword.create("SecurePass123");
expect(result.isSuccess).toBe(true);
const isValid = await result.data.compare("WrongPassword");
const isValid = await result.data.verifyPassword("WrongPassword");
expect(isValid).toBe(false);
});
});

View File

@ -0,0 +1,35 @@
import { Result, ValueObject } from "@common/domain";
import bcrypt from "bcrypt";
import { z } from "zod";
export class HashPassword extends ValueObject<string> {
private static readonly SALT_ROUNDS = 10;
static create(plainPassword: string): Result<HashPassword, Error> {
const result = HashPassword.validate(plainPassword);
if (!result.success) {
return Result.fail(new Error(result.error.errors[0].message));
}
const hashed = bcrypt.hashSync(result.data, this.SALT_ROUNDS);
return Result.ok(new HashPassword(hashed));
}
private static validate(password: string) {
const schema = z.string().min(6, { message: "Password must be at least 6 characters long" });
return schema.safeParse(password);
}
static createFromHash(hashedPassword: string): Result<HashPassword, Error> {
return Result.ok(new HashPassword(hashedPassword));
}
static createFromPlainText(plainTextPassword: string): Result<HashPassword, Error> {
return HashPassword.create(plainTextPassword);
}
async verifyPassword(plainTextPassword: string): Promise<boolean> {
return await bcrypt.compare(plainTextPassword, this._value);
}
}

View File

@ -1,4 +1,5 @@
export * from "./auth-user-roles";
export * from "./email-address";
export * from "./password-hash";
export * from "./hash-password";
export * from "./plain-password";
export * from "./username";

View File

@ -1,31 +0,0 @@
import { Result, ValueObject } from "@common/domain";
import bcrypt from "bcrypt";
import { z } from "zod";
export class PasswordHash extends ValueObject<string> {
private static readonly SALT_ROUNDS = 10;
static create(plainPassword: string): Result<PasswordHash, Error> {
const result = PasswordHash.validate(plainPassword);
if (!result.success) {
return Result.fail(new Error(result.error.errors[0].message));
}
const hashed = bcrypt.hashSync(result.data, this.SALT_ROUNDS);
return Result.ok(new PasswordHash(hashed));
}
private static validate(password: string) {
const schema = z.string().min(6, { message: "Password must be at least 6 characters long" });
return schema.safeParse(password);
}
static fromHash(hash: string): PasswordHash {
return new PasswordHash(hash);
}
async compare(plainPassword: string): Promise<boolean> {
return await bcrypt.compare(plainPassword, this._value);
}
}

View File

@ -0,0 +1,19 @@
import { Result, ValueObject } from "@common/domain";
import { z } from "zod";
export class PlainPassword extends ValueObject<string> {
static create(plainTextPassword: string): Result<PlainPassword, Error> {
const result = PlainPassword.validate(plainTextPassword);
if (!result.success) {
return Result.fail(new Error(result.error.errors[0].message));
}
return Result.ok(new PlainPassword(result.data));
}
private static validate(password: string) {
const schema = z.string().min(6, { message: "Password must be at least 6 characters long" });
return schema.safeParse(password);
}
}

View File

@ -1,7 +1,8 @@
import { Result } from "@common/domain";
import { AuthenticatedUser } from "@contexts/auth/domain";
import { AuthUserModel } from "../sequelize";
export interface IAuthenticatedUserMapper {
toDomain(entity: any): Result<AuthenticatedUser, Error>;
toPersistence(aggregate: AuthenticatedUser): any;
toDomain(entity: AuthUserModel): Result<AuthenticatedUser, Error>;
toPersistence(aggregate: AuthenticatedUser): AuthUserModel;
}

View File

@ -1,12 +1,13 @@
import { Result, UniqueID } from "@common/domain";
import { AuthenticatedUser, EmailAddress, PasswordHash, Username } from "@contexts/auth/domain";
import { AuthenticatedUser, EmailAddress, HashPassword, Username } from "@contexts/auth/domain";
import { AuthUserModel } from "../sequelize";
import { IAuthenticatedUserMapper } from "./authenticated-user-mapper.interface";
export class AuthenticatedUserMapper implements IAuthenticatedUserMapper {
/**
* 🔹 Convierte una entidad de la base de datos en un agregado de dominio `AuthenticatedUser`
*/
toDomain(entity: any): Result<AuthenticatedUser, Error> {
toDomain(entity: AuthUserModel): Result<AuthenticatedUser, Error> {
if (!entity) {
return Result.fail(new Error("Entity not found"));
}
@ -14,7 +15,7 @@ export class AuthenticatedUserMapper implements IAuthenticatedUserMapper {
// Crear Value Objects asegurando que sean válidos
const uniqueIdResult = UniqueID.create(entity.id);
const usernameResult = Username.create(entity.username);
const passwordHashResult = PasswordHash.create(entity.passwordHash);
const passwordHashResult = HashPassword.createFromHash(entity.hash_password);
const emailResult = EmailAddress.create(entity.email);
// Validar que no haya errores en la creación de los Value Objects
@ -33,7 +34,7 @@ export class AuthenticatedUserMapper implements IAuthenticatedUserMapper {
{
username: usernameResult.data!,
email: emailResult.data!,
passwordHash: passwordHashResult.data!,
hashPassword: passwordHashResult.data!,
roles: entity.roles || [],
},
uniqueIdResult.data!
@ -43,7 +44,7 @@ export class AuthenticatedUserMapper implements IAuthenticatedUserMapper {
/**
* 🔹 Convierte un agregado `AuthenticatedUser` en un objeto listo para persistencia
*/
toPersistence(authenticatedUser: AuthenticatedUser): any {
toPersistence(authenticatedUser: AuthenticatedUser): AuthUserModel {
return authenticatedUser.toPersistenceData();
}
}

View File

@ -1,7 +1,8 @@
import { Result } from "@common/domain";
import { TabContext } from "@contexts/auth/domain";
import { TabContextModel } from "../sequelize";
export interface ITabContextMapper {
toDomain(entity: any): Result<TabContext, Error>;
toPersistence(aggregate: TabContext): any;
toDomain(entity: TabContextModel): Result<TabContext, Error>;
toPersistence(aggregate: TabContext): TabContextModel;
}

View File

@ -1,9 +1,10 @@
import { Result, UniqueID } from "@common/domain";
import { TabContext } from "@contexts/auth/domain";
import { TabContextModel } from "../sequelize";
import { ITabContextMapper } from "./tab-context-mapper.interface";
export class TabContextMapper implements ITabContextMapper {
toDomain(entity: any): Result<TabContext, Error> {
toDomain(entity: TabContextModel): Result<TabContext, Error> {
if (!entity) {
return Result.fail(new Error("Entity not found"));
}
@ -39,7 +40,7 @@ export class TabContextMapper implements ITabContextMapper {
);
}
toPersistence(tabContext: TabContext): any {
toPersistence(tabContext: TabContext): TabContextModel {
return tabContext.toPersistenceData();
}
}

View File

@ -5,6 +5,7 @@ import {
AuthenticatedUser,
EmailAddress,
IAuthenticatedUserRepository,
PlainPassword,
} from "@contexts/auth/domain";
import jwt from "jsonwebtoken";
import passport from "passport";
@ -20,6 +21,22 @@ export class PassportAuthProvider implements IAuthProvider {
private readonly _repository: IAuthenticatedUserRepository;
private readonly _transactionManager!: ITransactionManager;
private async _verifyUser(email: string, password: string): Promise<AuthenticatedUser | null> {
const emailVO = EmailAddress.create(email);
if (emailVO.isFailure) return Promise.resolve(null);
const passwordVO = PlainPassword.create(password);
if (passwordVO.isFailure) return Promise.resolve(null);
const userResult = await this._repository.getUserByEmail(emailVO.data);
if (userResult.isFailure || !userResult.data) return Promise.resolve(null);
const user = userResult.data;
const isValidPassword = await user.verifyPassword(passwordVO.data);
return !isValidPassword ? Promise.resolve(null) : Promise.resolve(user);
}
/**
* 🔹 Configura PassportJS
*/
@ -31,10 +48,9 @@ export class PassportAuthProvider implements IAuthProvider {
passport.use(
"jwt",
new JwtStrategy(jwtOptions, (payload, done) => {
new JwtStrategy(jwtOptions, (tokenPayload, done) => {
try {
console.log(payload);
return done(null, payload);
return done(null, tokenPayload);
} catch (error) {
return done(error, false);
}
@ -47,7 +63,7 @@ export class PassportAuthProvider implements IAuthProvider {
{ usernameField: "email", passwordField: "password" },
async (email, password, done) => {
try {
const user = await this.verifyUser(email, password);
const user = await this._verifyUser(email, password);
return user
? done(null, user)
: done(null, false, { message: "Invalid email or password" });
@ -67,30 +83,17 @@ export class PassportAuthProvider implements IAuthProvider {
this.initializePassport();
}
generateAccessToken(payload: any): string {
return jwt.sign(payload, SECRET_KEY, { expiresIn: ACCESS_EXPIRATION });
generateAccessToken(payload: object): string {
return jwt.sign(payload, SECRET_KEY, { expiresIn: String(ACCESS_EXPIRATION) });
}
generateRefreshToken(payload: any): string {
generateRefreshToken(payload: object): string {
return jwt.sign(payload, SECRET_KEY, { expiresIn: REFRESH_EXPIRATION });
}
verifyToken(token: string): any {
return jwt.verify(token, SECRET_KEY);
}
async verifyUser(email: string, password: string): Promise<AuthenticatedUser | null> {
const emailVO = EmailAddress.create(email);
if (emailVO.isFailure) return Promise.resolve(null);
const userResult = await this._repository.findUserByEmail(emailVO.data);
if (userResult.isFailure || !userResult.data) return Promise.resolve(null);
const user = userResult.data;
const isValidPassword = await user.comparePassword(password);
return !isValidPassword ? Promise.resolve(null) : Promise.resolve(user);
}
}
export const createPassportAuthProvider = (
@ -101,3 +104,5 @@ export const createPassportAuthProvider = (
const _repository = repository || createAuthenticatedUserRepository();
return new PassportAuthProvider(_repository, _transactionManager);
};
export const initializePassportAuthProvide = () => createPassportAuthProvider();

View File

@ -36,9 +36,8 @@ export class AuthUserModel extends Model<
declare id: string;
declare username: string;
declare email: string;
declare password: string;
declare hash_password: string;
declare roles: string[];
declare isActive: boolean;
declare contexts: NonAttribute<TabContextModel[]>;
}
@ -58,7 +57,7 @@ export default (sequelize: Sequelize) => {
type: DataTypes.STRING,
allowNull: false,
},
password: {
hash_password: {
type: DataTypes.STRING,
allowNull: false,
},
@ -75,10 +74,6 @@ export default (sequelize: Sequelize) => {
this.setDataValue("roles", rawValue);
},
},
isActive: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
},
{
sequelize,

View File

@ -49,15 +49,16 @@ export class AuthenticatedUserRepository
}
}
async findUserByEmail(
async getUserByEmail(
email: EmailAddress,
transaction?: Transaction
): Promise<Result<AuthenticatedUser, Error>> {
try {
const rawUser: any = await this._findById(
const rawUser: any = await this._getBy(
AuthUserModel,
"email",
email.toString(),
{},
transaction
);

View File

@ -1,7 +1,7 @@
import { UniqueID } from "@common/domain";
import { Result, UniqueID } from "@common/domain";
import { ExpressController } from "@common/presentation";
import { createAuthService, IAuthService } from "@contexts/auth/application";
import { EmailAddress, PasswordHash } from "@contexts/auth/domain";
import { EmailAddress, PlainPassword } from "@contexts/auth/domain";
import { ILoginPresenter, LoginPresenter } from "./login.presenter";
class LoginController extends ExpressController {
@ -17,16 +17,18 @@ class LoginController extends ExpressController {
async executeImpl() {
const tabId = this.req.headers["x-tab-id"];
const emailVO = EmailAddress.create(this.req.body.email);
const passwordHashVO = PasswordHash.create(this.req.body.password);
const plainPasswordVO = PlainPassword.create(this.req.body.password);
const tabIdVO = UniqueID.create(String(tabId));
if ([emailVO, passwordHashVO, tabIdVO].some((r) => r.isFailure)) {
return this.clientError("Invalid input data");
const resultValidation = Result.combine([emailVO, plainPasswordVO, tabIdVO]);
if (resultValidation.isFailure) {
return this.clientError("Invalid input data", resultValidation.error);
}
const userOrError = await this._authService.loginUser({
email: emailVO.data,
passwordHash: passwordHashVO.data,
plainPassword: plainPasswordVO.data,
tabId: tabIdVO.data,
});

View File

@ -0,0 +1 @@
export * from "./logout.controller";

View File

@ -0,0 +1,38 @@
import { UniqueID } from "@common/domain";
import { ExpressController } from "@common/presentation";
import { createAuthService, IAuthService } from "@contexts/auth/application";
class LogoutController extends ExpressController {
private readonly _authService!: IAuthService;
public constructor(authService: IAuthService) {
super();
this._authService = authService;
}
async executeImpl() {
const tabId = this.req.headers["x-tab-id"];
const tabIdVO = UniqueID.create(String(tabId));
if (tabIdVO.isFailure) {
return this.clientError("Invalid tab id", [tabIdVO.error]);
}
const userOrError = await this._authService.logoutUser({
email: emailVO.data,
plainPassword: plainPasswordVO.data,
tabId: tabIdVO.data,
});
if (userOrError.isFailure) {
return this.unauthorizedError(userOrError.error.message);
}
return this.ok();
}
}
export const createLogoutController = () => {
const authService = createAuthService();
return new LogoutController(authService);
};

View File

@ -1,6 +1,6 @@
import { ExpressController } from "@common/presentation";
import { createAuthService, IAuthService } from "@contexts/auth/application";
import { EmailAddress, PasswordHash, Username } from "@contexts/auth/domain";
import { EmailAddress, HashPassword, Username } from "@contexts/auth/domain";
import { IRegisterPresenter, RegisterPresenter } from "./register.presenter";
class RegisterController extends ExpressController {
@ -16,16 +16,16 @@ class RegisterController extends ExpressController {
async executeImpl() {
const emailVO = EmailAddress.create(this.req.body.email);
const usernameVO = Username.create(this.req.body.username);
const passwordHashVO = PasswordHash.create(this.req.body.password);
const hashPasswordVO = HashPassword.create(this.req.body.password);
if ([emailVO, usernameVO, passwordHashVO].some((r) => r.isFailure)) {
if ([emailVO, usernameVO, hashPasswordVO].some((r) => r.isFailure)) {
return this.clientError("Invalid input data");
}
const userOrError = await this._authService.registerUser({
username: usernameVO.data,
email: emailVO.data,
passwordHash: passwordHashVO.data,
hashPassword: hashPasswordVO.data,
});
if (userOrError.isFailure) {

View File

@ -10,10 +10,10 @@ interface AuthenticatedRequest extends Request {
}
// Middleware para autenticar usando passport con el local-jwt strategy
const authenticateJwt = passport.authenticate("jwt", { session: false });
const _authenticateJwt = passport.authenticate("jwt", { session: false });
// Comprueba el rol del usuario
const authorizeUser = (condition: (user: AuthenticatedUser) => boolean) => {
const _authorizeUser = (condition: (user: AuthenticatedUser) => boolean) => {
return (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
const user = req.user as AuthenticatedUser;
if (!user || !condition(user)) {
@ -33,14 +33,14 @@ const authorizeUser = (condition: (user: AuthenticatedUser) => boolean) => {
};
// Verifica que el usuario esté autenticado
export const checkUser = [authenticateJwt, authorizeUser((user) => user.isUser)];
export const validateUser = [_authenticateJwt, _authorizeUser((user) => user.isUser)];
// Verifica que el usuario sea administrador
export const checkIsAdmin = [authenticateJwt, authorizeUser((user) => user.isAdmin)];
export const validateUserIsAdmin = [_authenticateJwt, _authorizeUser((user) => user.isAdmin)];
// Middleware para verificar que el usuario sea administrador o el dueño de los datos (self)
export const checkAdminOrSelf = [
authenticateJwt,
export const validateUserIsAdminOrOwner = [
_authenticateJwt,
(req: AuthenticatedRequest, res: Response, next: NextFunction) => {
const user = req.user as AuthenticatedUser;
const { userId } = req.params;

View File

@ -1,25 +1,21 @@
import { UniqueID } from "@common/domain";
import { ApiError, ExpressController } from "@common/presentation";
import { createTabContextService } from "@contexts/auth/application";
import { TabContext } from "@contexts/auth/domain";
import { NextFunction, Request, Response } from "express";
import httpStatus from "http-status";
export const validateTabHeader = (req: Request, res: Response, next: NextFunction) => {
const tabId = req.headers["x-tab-id"];
if (!tabId) {
return ExpressController.errorResponse(
new ApiError({
status: 401,
title: httpStatus["401"],
name: httpStatus["401_NAME"],
detail: "Tab ID is required",
}),
res
);
}
next();
};
// Extender el Request de Express para incluir el usuario autenticado optionalmente
interface TabContextRequest extends Request {
tabContext?: TabContext;
}
export const validateTabContext = async (req: Request, res: Response, next: NextFunction) => {
const tabId = req.headers["x-tab-id"];
export const validateTabContextHeader = async (
req: TabContextRequest,
res: Response,
next: NextFunction
) => {
const tabId = String(req.headers["x-tab-id"]);
if (!tabId) {
return ExpressController.errorResponse(
new ApiError({
@ -32,7 +28,19 @@ export const validateTabContext = async (req: Request, res: Response, next: Next
);
}
const contextOrError = await TabContextRepository.getContextByTabId(tabId);
const tabIdOrError = UniqueID.create(tabId, false);
if (tabIdOrError.isFailure) {
return ExpressController.errorResponse(
new ApiError({
status: 422,
title: httpStatus["422"],
name: httpStatus["422_NAME"],
detail: "Invalid Tab ID",
}),
res
);
}
const contextOrError = await createTabContextService().getContextByTabId(tabIdOrError.data);
if (contextOrError.isFailure) {
return ExpressController.errorResponse(
new ApiError({
@ -47,6 +55,6 @@ export const validateTabContext = async (req: Request, res: Response, next: Next
const context = contextOrError.data;
req.user = { id: context.user_id, company_id: context.company_id };
req.tabContext = context;
next();
};

View File

@ -1,5 +1,5 @@
import { validateRequest } from "@common/presentation";
import { validateTabHeader } from "@contexts/auth/presentation";
import { validateTabContextHeader, validateUser } from "@contexts/auth/presentation";
import { createLoginController } from "@contexts/auth/presentation/controllers";
import { createRegisterController } from "@contexts/auth/presentation/controllers/register/register.controller";
import { LoginUserSchema, RegisterUserSchema } from "@contexts/auth/presentation/dto";
@ -32,6 +32,7 @@ export const authRouter = (appRouter: Router) => {
* @apiGroup Authentication
* @apiVersion 1.0.0
*
* @apiHeader {String} Tab ID (x-tab-id)
* @apiBody {String} email User's email address.
* @apiBody {String} password User's password.
*
@ -43,39 +44,27 @@ export const authRouter = (appRouter: Router) => {
authRoutes.post(
"/login",
validateRequest(LoginUserSchema),
validateTabHeader,
validateTabContextHeader,
(req, res, next) => {
createLoginController().execute(req, res, next);
}
);
/**
* @api {post} /api/auth/select-company Select an active company
* @apiName SelectCompany
* @apiGroup Authentication
* @apiVersion 1.0.0
*
* @apiHeader {String} Authorization Bearer token.
*
* @apiBody {String} companyId The ID of the company to select.
*
* @apiSuccess (200) {String} message Success message.
*
* @apiError (403) {String} message Unauthorized or invalid company selection.
*/
//authRoutes.post("/select-company", authMiddleware, authController.selectCompany);
/**
* @api {post} /api/auth/logout Logout user
* @apiName LogoutUser
* @apiGroup Authentication
* @apiVersion 1.0.0
*
* @apiHeader {String} Tab ID (x-tab-id)
* @apiHeader {String} Authorization Bearer token.
*
* @apiSuccess (200) {String} message Success message.
*/
//authRoutes.post("/logout", authMiddleware, authController.logout);
authRoutes.post("/logout", validateUser, validateTabContextHeader, (req, res, next) => {
res.sendStatus(200);
//createLogoutController().execute(req, res, next);
});
appRouter.use("/auth", authRoutes);
};