.
This commit is contained in:
parent
8ead5a62da
commit
36788f34e8
@ -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"
|
||||
|
||||
@ -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
@ -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"}
|
||||
@ -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}`);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>>;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
);
|
||||
|
||||
|
||||
@ -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,
|
||||
});
|
||||
|
||||
|
||||
@ -0,0 +1 @@
|
||||
export * from "./logout.controller";
|
||||
@ -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);
|
||||
};
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user