From 6cf7ce13971faab6455cf848349d7bc088b11f34 Mon Sep 17 00:00:00 2001 From: Berkay Date: Sun, 27 Jul 2025 15:54:23 +0300 Subject: [PATCH] auth defined test required --- ServicesApi/package-lock.json | 268 ++++++++++++++++-- ServicesApi/package.json | 2 + ServicesApi/prisma/schema.prisma | 187 ++++++------ ServicesApi/src/auth/auth.controller.ts | 14 +- ServicesApi/src/auth/auth.module.ts | 2 +- ServicesApi/src/auth/auth.service.ts | 4 +- .../auth/password/change/change.service.ts | 194 ++++++++++++- .../src/auth/password/change/dtoValidator.ts | 14 + .../auth/password/create/create.service.ts | 66 ++++- .../src/auth/password/create/dtoValidator.ts | 12 + .../src/auth/password/reset/dtoValidator.ts | 6 + .../src/auth/password/reset/reset.service.ts | 34 ++- .../auth/password/verify-otp/dtoValidator.ts | 8 + .../password/verify-otp/verify-otp.service.ts | 19 ++ .../src/middleware/access-control.guard.ts | 21 +- ServicesApi/src/utils/auth/login_handler.ts | 2 - ServicesApi/src/utils/auth/redis_handlers.ts | 151 +++++++++- 17 files changed, 857 insertions(+), 147 deletions(-) create mode 100644 ServicesApi/src/auth/password/change/dtoValidator.ts create mode 100644 ServicesApi/src/auth/password/create/dtoValidator.ts create mode 100644 ServicesApi/src/auth/password/reset/dtoValidator.ts create mode 100644 ServicesApi/src/auth/password/verify-otp/dtoValidator.ts diff --git a/ServicesApi/package-lock.json b/ServicesApi/package-lock.json index aba49af..a8b7804 100644 --- a/ServicesApi/package-lock.json +++ b/ServicesApi/package-lock.json @@ -17,6 +17,8 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.2", "ioredis": "^5.6.1", + "otplib": "^12.0.1", + "qrcode": "^1.5.4", "redis": "^5.6.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", @@ -2767,6 +2769,53 @@ "npm": ">=5.10.0" } }, + "node_modules/@otplib/core": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz", + "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==", + "license": "MIT" + }, + "node_modules/@otplib/plugin-crypto": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz", + "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==", + "license": "MIT", + "dependencies": { + "@otplib/core": "^12.0.1" + } + }, + "node_modules/@otplib/plugin-thirty-two": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz", + "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==", + "license": "MIT", + "dependencies": { + "@otplib/core": "^12.0.1", + "thirty-two": "^1.0.2" + } + }, + "node_modules/@otplib/preset-default": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz", + "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==", + "license": "MIT", + "dependencies": { + "@otplib/core": "^12.0.1", + "@otplib/plugin-crypto": "^12.0.1", + "@otplib/plugin-thirty-two": "^12.0.1" + } + }, + "node_modules/@otplib/preset-v11": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz", + "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==", + "license": "MIT", + "dependencies": { + "@otplib/core": "^12.0.1", + "@otplib/plugin-crypto": "^12.0.1", + "@otplib/plugin-thirty-two": "^12.0.1" + } + }, "node_modules/@paralleldrive/cuid2": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", @@ -4511,7 +4560,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -5078,7 +5126,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5354,7 +5401,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5367,7 +5413,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -5613,6 +5658,15 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -5766,6 +5820,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -5833,7 +5893,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/encodeurl": { @@ -6841,7 +6900,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -7342,7 +7400,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9056,6 +9113,17 @@ "node": ">=0.10.0" } }, + "node_modules/otplib": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", + "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==", + "license": "MIT", + "dependencies": { + "@otplib/core": "^12.0.1", + "@otplib/preset-default": "^12.0.1", + "@otplib/preset-v11": "^12.0.1" + } + }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -9102,7 +9170,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -9160,7 +9227,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9365,6 +9431,15 @@ "node": ">=4" } }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9512,6 +9587,148 @@ ], "license": "MIT" }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/qrcode/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qrcode/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/qrcode/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -9687,7 +9904,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9703,6 +9919,12 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -10029,6 +10251,12 @@ "node": ">= 18" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -10334,7 +10562,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -10388,7 +10615,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10398,7 +10624,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -10830,6 +11055,14 @@ "b4a": "^1.6.4" } }, + "node_modules/thirty-two": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", + "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==", + "engines": { + "node": ">=0.2.6" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -11435,6 +11668,12 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -11449,7 +11688,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -11506,7 +11744,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -11516,7 +11753,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" diff --git a/ServicesApi/package.json b/ServicesApi/package.json index b5d0a94..221d538 100644 --- a/ServicesApi/package.json +++ b/ServicesApi/package.json @@ -28,6 +28,8 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.2", "ioredis": "^5.6.1", + "otplib": "^12.0.1", + "qrcode": "^1.5.4", "redis": "^5.6.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", diff --git a/ServicesApi/prisma/schema.prisma b/ServicesApi/prisma/schema.prisma index 2f4aa8f..959d5b6 100644 --- a/ServicesApi/prisma/schema.prisma +++ b/ServicesApi/prisma/schema.prisma @@ -32,7 +32,7 @@ model account_books { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? companies_account_books_branch_idTocompanies companies @relation("account_books_branch_idTocompanies", fields: [branch_id], references: [id], onDelete: NoAction, onUpdate: NoAction) companies_account_books_company_idTocompanies companies @relation("account_books_company_idTocompanies", fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -73,7 +73,7 @@ model account_code_parser { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_codes account_codes @relation(fields: [account_code_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -118,7 +118,7 @@ model account_codes { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_code_parser account_code_parser[] companies_account_codes_company_idTocompanies companies @relation("account_codes_company_idTocompanies", fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -173,7 +173,7 @@ model account_delay_interest { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) bank_resp_company_id Int? bank_resp_company_uu_id String? @db.VarChar account_records account_records @relation(fields: [account_records_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -250,7 +250,7 @@ model account_detail { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_codes account_codes @relation(fields: [account_code_id], references: [id], onDelete: NoAction, onUpdate: NoAction) account_books account_books @relation(fields: [account_header_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -322,7 +322,7 @@ model account_master { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_detail account_detail[] account_books account_books @relation(fields: [account_header_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -363,7 +363,7 @@ model account_record_exchanges { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_records account_records @relation(fields: [account_records_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -442,7 +442,7 @@ model account_records { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? payment_result_type Int? payment_result_type_uu_id String? @db.VarChar @@ -501,7 +501,7 @@ model account_records_model_train { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) is_model_trained Boolean @default(false) trained_at DateTime? @db.Timestamptz(6) account_records account_records @relation(fields: [account_records_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -540,7 +540,7 @@ model account_records_predict { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) prediction_model String @db.VarChar prediction_field String @default("") @db.VarChar account_records account_records @relation(fields: [account_records_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -578,7 +578,7 @@ model address_city { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_state address_state @relation(fields: [state_id], references: [id], onDelete: NoAction, onUpdate: NoAction) address_district address_district[] @@ -614,7 +614,7 @@ model address_country { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_state address_state[] @@ -651,7 +651,7 @@ model address_district { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_city address_city @relation(fields: [city_id], references: [id], onDelete: NoAction, onUpdate: NoAction) address_locality address_locality[] @@ -692,7 +692,7 @@ model address_geographic_locations { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? @@index([geo_table, geo_id], map: "_address_geographic_locations_ndx_00") @@ -731,7 +731,7 @@ model address_locality { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_district address_district @relation(fields: [district_id], references: [id], onDelete: NoAction, onUpdate: NoAction) address_neighborhood address_neighborhood[] @@ -773,7 +773,7 @@ model address_neighborhood { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_district address_district? @relation(fields: [district_id], references: [id], onDelete: NoAction, onUpdate: NoAction) address_locality address_locality? @relation(fields: [locality_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -808,7 +808,7 @@ model address_postcode { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_street address_street @relation(fields: [street_id], references: [id], onDelete: NoAction, onUpdate: NoAction) relationship_employee2postcode relationship_employee2postcode[] @@ -846,7 +846,7 @@ model address_state { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_city address_city[] address_country address_country @relation(fields: [country_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -885,7 +885,7 @@ model address_street { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_postcode address_postcode[] address_neighborhood address_neighborhood @relation(fields: [neighborhood_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -927,7 +927,7 @@ model addresses { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? address_street address_street @relation(fields: [street_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build build[] @@ -967,7 +967,7 @@ model api_enum_dropdown { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? lang String @default("tr") @db.VarChar account_detail account_detail[] @@ -1014,7 +1014,7 @@ model application2employee { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? employees employees @relation(fields: [employee_id], references: [id], onDelete: NoAction, onUpdate: NoAction) services services @relation(fields: [service_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1051,7 +1051,7 @@ model application2employee_extra { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? applications applications @relation(fields: [application_id], references: [id], onDelete: NoAction, onUpdate: NoAction) employees employees @relation(fields: [employee_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1086,7 +1086,7 @@ model application2occupant { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_living_space build_living_space @relation(fields: [build_living_space_id], references: [id], onDelete: NoAction, onUpdate: NoAction) services services @relation(fields: [service_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1123,7 +1123,7 @@ model application2occupant_extra { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? applications applications @relation(fields: [application_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build_living_space build_living_space @relation(fields: [build_living_space_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1160,7 +1160,7 @@ model applications { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? application2employee_extra application2employee_extra[] application2occupant_extra application2occupant_extra[] @@ -1213,7 +1213,7 @@ model build { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_records account_records[] addresses addresses @relation(fields: [address_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1268,7 +1268,7 @@ model build_area { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build build @relation(fields: [build_id], references: [id], onDelete: NoAction, onUpdate: NoAction) api_enum_dropdown api_enum_dropdown? @relation(fields: [part_type_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1306,7 +1306,7 @@ model build_companies_providing { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build build @relation(fields: [build_id], references: [id], onDelete: NoAction, onUpdate: NoAction) companies_build_companies_providing_company_idTocompanies companies @relation("build_companies_providing_company_idTocompanies", fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1352,7 +1352,7 @@ model build_decision_book { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_records account_records[] build build @relation(fields: [build_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1403,7 +1403,7 @@ model build_decision_book_invitations { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book build_decision_book @relation(fields: [decision_book_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build_decision_book_person build_decision_book_person[] @@ -1445,7 +1445,7 @@ model build_decision_book_items { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book build_decision_book @relation(fields: [build_decision_book_id], references: [id], onDelete: NoAction, onUpdate: NoAction) api_enum_dropdown api_enum_dropdown? @relation(fields: [info_type_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1490,7 +1490,7 @@ model build_decision_book_items_unapproved { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book_items_build_decision_book_items_unapproved_build_decision_book_itemTobuild_decision_book_items build_decision_book_items @relation("build_decision_book_items_unapproved_build_decision_book_itemTobuild_decision_book_items", fields: [build_decision_book_item], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "build_decision_book_items_unappro_build_decision_book_item_fkey") build_decision_book_items_build_decision_book_items_unapproved_decision_book_item_idTobuild_decision_book_items build_decision_book_items @relation("build_decision_book_items_unapproved_decision_book_item_idTobuild_decision_book_items", fields: [decision_book_item_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1548,7 +1548,7 @@ model build_decision_book_legal { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book_items build_decision_book_items @relation(fields: [build_db_item_id], references: [id], onDelete: NoAction, onUpdate: NoAction) people_build_decision_book_legal_mediator_lawyer_person_idTopeople people @relation("build_decision_book_legal_mediator_lawyer_person_idTopeople", fields: [mediator_lawyer_person_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1598,7 +1598,7 @@ model build_decision_book_payments { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) account_is_debit Boolean? @default(true) build_decision_book_id Int? build_decision_book_uu_id String? @db.VarChar @@ -1657,7 +1657,7 @@ model build_decision_book_person { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book build_decision_book @relation(fields: [build_decision_book_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build_living_space build_living_space @relation(fields: [build_living_space_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1698,7 +1698,7 @@ model build_decision_book_person_occupants { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book_person build_decision_book_person @relation(fields: [build_decision_book_person_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "build_decision_book_person_oc_build_decision_book_person_i_fkey") build_decision_book_invitations build_decision_book_invitations? @relation(fields: [invite_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1737,7 +1737,7 @@ model build_decision_book_project_items { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book_projects build_decision_book_projects @relation(fields: [build_decision_book_project_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "build_decision_book_project_i_build_decision_book_project__fkey") @@ -1774,7 +1774,7 @@ model build_decision_book_project_person { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book_projects build_decision_book_projects @relation(fields: [build_decision_book_project_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "build_decision_book_project_p_build_decision_book_project__fkey") build_living_space build_living_space @relation(fields: [living_space_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1830,7 +1830,7 @@ model build_decision_book_projects { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_detail account_detail[] account_master account_master[] @@ -1879,7 +1879,7 @@ model build_iban_description { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_parts build_parts? @relation(fields: [build_parts_id], references: [id], onDelete: NoAction, onUpdate: NoAction) companies companies? @relation(fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1919,7 +1919,7 @@ model build_ibans { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build build? @relation(fields: [build_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -1961,7 +1961,7 @@ model build_living_space { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_records account_records[] application2occupant application2occupant[] @@ -2011,7 +2011,7 @@ model build_management { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build build @relation(fields: [build_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build_parts build_parts @relation(fields: [build_parts_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2059,7 +2059,7 @@ model build_parts { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_records account_records[] build_decision_book_payments build_decision_book_payments[] @@ -2105,7 +2105,7 @@ model build_person_providing { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build build @relation(fields: [build_id], references: [id], onDelete: NoAction, onUpdate: NoAction) companies companies? @relation(fields: [contract_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2142,7 +2142,7 @@ model build_sites { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build build[] addresses addresses @relation(fields: [address_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2177,7 +2177,7 @@ model build_types { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? @@unique([type_code, function_code, lang], map: "_build_types_ndx_00") @@ -2222,7 +2222,7 @@ model companies { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_books_account_books_branch_idTocompanies account_books[] @relation("account_books_branch_idTocompanies") account_books_account_books_company_idTocompanies account_books[] @relation("account_books_company_idTocompanies") @@ -2290,7 +2290,7 @@ model company_delay_interest { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) build build? @relation(fields: [build_id], references: [id], onDelete: NoAction, onUpdate: NoAction) companies companies? @relation(fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2331,7 +2331,7 @@ model contracts { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book build_decision_book[] build_decision_book_projects build_decision_book_projects[] @@ -2373,7 +2373,7 @@ model credentials { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? people people @relation(fields: [person_id], references: [id], onDelete: NoAction, onUpdate: NoAction) users users @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2417,7 +2417,7 @@ model decision_book_budget_books { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? companies_decision_book_budget_books_branch_idTocompanies companies? @relation("decision_book_budget_books_branch_idTocompanies", fields: [branch_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build_decision_book build_decision_book @relation(fields: [build_decision_book_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2458,7 +2458,7 @@ model decision_book_budget_codes { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book build_decision_book? @relation(fields: [build_decision_book_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build_parts build_parts? @relation(fields: [build_parts_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2501,7 +2501,7 @@ model decision_book_budget_master { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? decision_book_budget_books decision_book_budget_books @relation(fields: [budget_books_id], references: [id], onDelete: NoAction, onUpdate: NoAction) departments departments @relation(fields: [department_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2540,7 +2540,7 @@ model decision_book_budgets { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? decision_book_budget_codes decision_book_budget_codes @relation(fields: [budget_codes_id], references: [id], onDelete: NoAction, onUpdate: NoAction) decision_book_budget_master decision_book_budget_master @relation(fields: [decision_book_budget_master_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2577,7 +2577,7 @@ model departments { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? account_master account_master[] decision_book_budget_master decision_book_budget_master[] @@ -2618,7 +2618,7 @@ model duties { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? departments departments @relation(fields: [department_id], references: [id], onDelete: NoAction, onUpdate: NoAction) duty_duties_duties_idToduty duty @relation("duties_duties_idToduty", fields: [duties_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2656,7 +2656,7 @@ model duty { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? duties_duties_duties_idToduty duties[] @relation("duties_duties_idToduty") duties_duties_users_default_dutyToduty duties[] @relation("duties_users_default_dutyToduty") @@ -2690,7 +2690,7 @@ model employee_history { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? people people @relation(fields: [people_id], references: [id], onDelete: NoAction, onUpdate: NoAction) staff staff @relation(fields: [staff_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2725,7 +2725,7 @@ model employee_salaries { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? people people @relation(fields: [people_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2759,7 +2759,7 @@ model employees { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? application2employee application2employee[] application2employee_extra application2employee_extra[] @@ -2802,7 +2802,7 @@ model endpoint_restriction { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? events events[] @@ -2836,7 +2836,7 @@ model event2employee { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? employees employees @relation(fields: [employee_id], references: [id], onDelete: NoAction, onUpdate: NoAction) services services @relation(fields: [event_service_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2871,7 +2871,7 @@ model event2employee_extra { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? employees employees @relation(fields: [employee_id], references: [id], onDelete: NoAction, onUpdate: NoAction) events events @relation(fields: [event_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2906,7 +2906,7 @@ model event2occupant { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_living_space build_living_space @relation(fields: [build_living_space_id], references: [id], onDelete: NoAction, onUpdate: NoAction) services services @relation(fields: [event_service_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2941,7 +2941,7 @@ model event2occupant_extra { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_living_space build_living_space @relation(fields: [build_living_space_id], references: [id], onDelete: NoAction, onUpdate: NoAction) events events @relation(fields: [event_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -2982,7 +2982,7 @@ model events { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? event2employee_extra event2employee_extra[] event2occupant_extra event2occupant_extra[] @@ -3025,7 +3025,7 @@ model module_price { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? events events @relation(fields: [event_id], references: [id], onDelete: NoAction, onUpdate: NoAction) modules modules @relation(fields: [module_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3061,7 +3061,7 @@ model modules { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? module_price module_price[] services services[] @@ -3098,7 +3098,7 @@ model occupant_types { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? build_decision_book_person_occupants build_decision_book_person_occupants[] build_living_space build_living_space[] @@ -3132,7 +3132,7 @@ model part2employee { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? employees employees @relation(fields: [employee_id], references: [id], onDelete: NoAction, onUpdate: NoAction) build_parts build_parts @relation(fields: [part_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3176,7 +3176,7 @@ model people { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? birthname String? @db.VarChar account_codes account_codes[] @@ -3231,7 +3231,7 @@ model relationship_duty_company { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? duties duties @relation(fields: [duties_id], references: [id], onDelete: NoAction, onUpdate: NoAction) companies_relationship_duty_company_member_idTocompanies companies @relation("relationship_duty_company_member_idTocompanies", fields: [member_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3269,7 +3269,7 @@ model relationship_duty_people { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? companies companies @relation(fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) duties duties @relation(fields: [duties_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3306,7 +3306,7 @@ model relationship_employee2build { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? companies companies @relation(fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) employees employees @relation(fields: [employee_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3343,7 +3343,7 @@ model relationship_employee2postcode { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? companies companies? @relation(fields: [company_id], references: [id], onDelete: NoAction, onUpdate: NoAction) employees employees @relation(fields: [employee_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3380,7 +3380,7 @@ model services { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? application2employee application2employee[] application2occupant application2occupant[] @@ -3422,7 +3422,7 @@ model services2applications { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? applications applications @relation(fields: [application_id], references: [id], onDelete: NoAction, onUpdate: NoAction) services services @relation(fields: [service_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3456,7 +3456,7 @@ model services2events { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? events events @relation(fields: [event_id], references: [id], onDelete: NoAction, onUpdate: NoAction) services services @relation(fields: [service_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3492,7 +3492,7 @@ model staff { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? employee_history employee_history[] employees employees[] @@ -3537,7 +3537,7 @@ model users { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) default_language String @default("tr") @db.VarChar ref_int Int? credentials credentials[] @@ -3579,7 +3579,7 @@ model users_tokens { expiry_starts DateTime @default(now()) @db.Timestamptz(6) expiry_ends DateTime @default(now()) @db.Timestamptz(6) created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) ref_int Int? users users @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@ -3590,6 +3590,25 @@ model users_tokens { @@index([updated_at], map: "ix_users_tokens_updated_at") } +model password_history { + id Int @id @default(autoincrement()) + uu_id String @unique(map: "password_history_uu_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid + userUUID String @map("user_uuid") @db.Uuid + password String @db.VarChar + old_password_first String @db.VarChar + old_password_first_modified_at DateTime @db.Timestamptz(6) + old_password_second String @db.VarChar + old_password_second_modified_at DateTime @db.Timestamptz(6) + old_password_third String @db.VarChar + old_password_third_modified_at DateTime @db.Timestamptz(6) + created_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) + + @@index([created_at], map: "ix_password_history_created_at") + @@index([uu_id], map: "idx_password_history_uu_id") + @@index([updated_at], map: "ix_password_history_updated_at") +} + model domain_data { id Int @id @default(autoincrement()) uu_id String @unique(map: "domain_data_uu_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid @@ -3598,7 +3617,7 @@ model domain_data { mainDomain String? @map("main_domain") modifiedAt Float @map("modified_at") created_at DateTime @default(now()) @db.Timestamptz(6) - updated_at DateTime @default(now()) @db.Timestamptz(6) + updated_at DateTime @updatedAt @db.Timestamptz(6) users users @relation("UserDomainData", fields: [userUUID], references: [uu_id], onDelete: NoAction, onUpdate: NoAction, map: "domain_data_users_fkey") @@index([created_at], map: "ix_domain_data_created_at") diff --git a/ServicesApi/src/auth/auth.controller.ts b/ServicesApi/src/auth/auth.controller.ts index 8863546..570f3b0 100644 --- a/ServicesApi/src/auth/auth.controller.ts +++ b/ServicesApi/src/auth/auth.controller.ts @@ -8,12 +8,15 @@ import { Body, HttpCode, UseGuards, + Req, } from '@nestjs/common'; import { AuthService } from './auth.service'; import { userLoginValidator } from './login/dtoValidator'; import { userSelectValidator } from './select/dtoValidator'; import { userLogoutValidator } from './logout/dtoValidator'; import { AuthControlGuard } from '../middleware/access-control.guard'; +import { userCreatePasswordValidator } from './password/create/dtoValidator'; +import { userChangePasswordValidator } from './password/change/dtoValidator'; @Controller('auth') export class AuthController { @@ -34,15 +37,18 @@ export class AuthController { @Post('/password/create') @HttpCode(200) - async createPassword() { - return { message: 'Password created successfully' }; + async createPassword(@Body() query: userCreatePasswordValidator) { + return await this.authService.createPassword(query); } @Post('/password/change') @HttpCode(200) @UseGuards(AuthControlGuard) - async changePassword() { - return { message: 'Password changed successfully' }; + async changePassword( + @Body() query: userChangePasswordValidator, + @Req() req: Request, + ) { + return await this.authService.changePassword(query, req); } @Post('/password/reset') diff --git a/ServicesApi/src/auth/auth.module.ts b/ServicesApi/src/auth/auth.module.ts index d300f6b..20d223d 100644 --- a/ServicesApi/src/auth/auth.module.ts +++ b/ServicesApi/src/auth/auth.module.ts @@ -21,8 +21,8 @@ import { DisconnectService } from './disconnect/disconnect.service'; LogoutService, SelectService, CreatePasswordService, - ResetPasswordService, ChangePasswordService, + ResetPasswordService, VerifyOtpService, DisconnectService, PrismaService, diff --git a/ServicesApi/src/auth/auth.service.ts b/ServicesApi/src/auth/auth.service.ts index 70e00e1..b72b656 100644 --- a/ServicesApi/src/auth/auth.service.ts +++ b/ServicesApi/src/auth/auth.service.ts @@ -40,8 +40,8 @@ export class AuthService { return await this.createPasswordService.run(dto); } - async changePassword(dto: any) { - return await this.changePasswordService.run(dto); + async changePassword(dto: any, req: Request) { + return await this.changePasswordService.run(dto, req); } async resetPassword(dto: any) { diff --git a/ServicesApi/src/auth/password/change/change.service.ts b/ServicesApi/src/auth/password/change/change.service.ts index ee19db4..b5e9f40 100644 --- a/ServicesApi/src/auth/password/change/change.service.ts +++ b/ServicesApi/src/auth/password/change/change.service.ts @@ -1,8 +1,196 @@ -import { Injectable } from '@nestjs/common'; +import { PrismaService } from '@/src/prisma.service'; +import { + Injectable, + BadRequestException, + UnauthorizedException, +} from '@nestjs/common'; +import { userChangePasswordValidator } from './dtoValidator'; +import { RedisHandlers } from '@/src/utils/auth/redis_handlers'; +import { PasswordHandlers } from '@/src/utils/auth/login_handler'; @Injectable() export class ChangePasswordService { - async run(dto: any) { - return dto; + constructor( + private readonly prisma: PrismaService, + private readonly redis: RedisHandlers, + private readonly passHandlers: PasswordHandlers, + ) {} + + private async syncPasswordHistory( + foundUser: any, + dto: userChangePasswordValidator, + hashPassword: string, + ) { + const passwordHistory = await this.prisma.password_history.findFirst({ + where: { userUUID: foundUser.uu_id }, + }); + console.log('passwordHistory', passwordHistory); + console.log('dto', dto); + console.log('hashPassword', hashPassword); + + if (passwordHistory) { + if (!passwordHistory.old_password_first) { + await this.prisma.password_history.update({ + where: { id: passwordHistory.id }, + data: { + password: hashPassword, + old_password_first: dto.password, + old_password_first_modified_at: new Date(), + }, + }); + } else if (!passwordHistory.old_password_second) { + await this.prisma.password_history.update({ + where: { id: passwordHistory.id }, + data: { + password: hashPassword, + old_password_second: dto.password, + old_password_second_modified_at: new Date(), + }, + }); + } else if (!passwordHistory.old_password_third) { + await this.prisma.password_history.update({ + where: { id: passwordHistory.id }, + data: { + password: hashPassword, + old_password_third: dto.password, + old_password_third_modified_at: new Date(), + }, + }); + } else { + const firstTimestamp = new Date( + passwordHistory.old_password_first_modified_at, + ).getTime(); + const secondTimestamp = new Date( + passwordHistory.old_password_second_modified_at, + ).getTime(); + const thirdTimestamp = new Date( + passwordHistory.old_password_third_modified_at, + ).getTime(); + + let oldestIndex = 'first'; + let oldestTimestamp = firstTimestamp; + + if (secondTimestamp < oldestTimestamp) { + oldestIndex = 'second'; + oldestTimestamp = secondTimestamp; + } + if (thirdTimestamp < oldestTimestamp) { + oldestIndex = 'third'; + } + + await this.prisma.password_history.update({ + where: { id: passwordHistory.id }, + data: { + password: hashPassword, + ...(oldestIndex === 'first' + ? { + old_password_first: dto.password, + old_password_first_modified_at: new Date(), + } + : oldestIndex === 'second' + ? { + old_password_second: dto.password, + old_password_second_modified_at: new Date(), + } + : { + old_password_third: dto.password, + old_password_third_modified_at: new Date(), + }), + }, + }); + } + } else { + await this.prisma.password_history.create({ + data: { + userUUID: foundUser.uu_id, + password: hashPassword, + old_password_first: dto.password, + old_password_first_modified_at: new Date(), + old_password_second: '', + old_password_second_modified_at: new Date(), + old_password_third: '', + old_password_third_modified_at: new Date(), + }, + }); + } + } + + async run(dto: userChangePasswordValidator, req: Request) { + const isValid = () => { + const isOldPasswordDifferent = dto.password !== dto.oldPassword; + const isPasswordMatchesWithRePassword = dto.password === dto.rePassword; + return isOldPasswordDifferent && isPasswordMatchesWithRePassword; + }; + + if (!isValid()) { + throw new BadRequestException( + 'Passwords do not match or new password is the same as old password', + ); + } + const accessObject = await this.redis.getLoginFromRedis(req); + const userFromRedis = accessObject?.value.users; + if (!userFromRedis) { + throw new UnauthorizedException('User not authenticated'); + } + + const foundUser = await this.prisma.users.findFirstOrThrow({ + where: { uu_id: userFromRedis.uu_id }, + }); + + if (foundUser.password_token) { + throw new BadRequestException('Set password first before changing'); + } + const isPasswordValid = this.passHandlers.check_password( + foundUser.uu_id, + dto.oldPassword, + foundUser.hash_password, + ); + if (!isPasswordValid) { + throw new UnauthorizedException('Invalid password'); + } + + const passwordHistory = await this.prisma.password_history.findFirst({ + where: { + userUUID: foundUser.uu_id, + OR: [ + { + old_password_first: { + equals: dto.password, + mode: 'insensitive', + }, + }, + { + old_password_second: { + equals: dto.password, + mode: 'insensitive', + }, + }, + { + old_password_third: { + equals: dto.password, + mode: 'insensitive', + }, + }, + ], + }, + }); + if (passwordHistory) { + throw new UnauthorizedException( + 'Invalid password, new password can not be same as old password', + ); + } + + const hashPassword = this.passHandlers.create_hashed_password( + foundUser.uu_id, + dto.password, + ); + await this.prisma.users.update({ + where: { id: foundUser.id }, + data: { + hash_password: hashPassword, + }, + }); + await this.syncPasswordHistory(foundUser, dto, hashPassword); + return { message: 'Password changed successfully' }; } } diff --git a/ServicesApi/src/auth/password/change/dtoValidator.ts b/ServicesApi/src/auth/password/change/dtoValidator.ts new file mode 100644 index 0000000..830b1e0 --- /dev/null +++ b/ServicesApi/src/auth/password/change/dtoValidator.ts @@ -0,0 +1,14 @@ +import { IsString } from 'class-validator'; + +export class userChangePasswordValidator { + @IsString() + oldPassword: string; + + @IsString() + password: string; + + @IsString() + rePassword: string; + + +} diff --git a/ServicesApi/src/auth/password/create/create.service.ts b/ServicesApi/src/auth/password/create/create.service.ts index bf54ff7..6b10ab9 100644 --- a/ServicesApi/src/auth/password/create/create.service.ts +++ b/ServicesApi/src/auth/password/create/create.service.ts @@ -1,8 +1,70 @@ -import { Injectable } from '@nestjs/common'; +import { userCreatePasswordValidator } from './dtoValidator'; +import { PrismaService } from '@/src/prisma.service'; +import { PasswordHandlers } from '@/src/utils/auth/login_handler'; +import { Injectable, BadRequestException } from '@nestjs/common'; @Injectable() export class CreatePasswordService { - async run(dto: any) { + constructor( + private readonly prisma: PrismaService, + private readonly passHandlers: PasswordHandlers, + ) {} + + async run(dto: userCreatePasswordValidator) { + if (dto.password !== dto.rePassword) { + throw new BadRequestException('Passwords do not match'); + } + const foundUser = await this.prisma.users.findFirstOrThrow({ + where: { password_token: dto.passwordToken }, + }); + + const passwordExpiryDate = new Date(foundUser.password_expiry_begins); + const passwordExpiryDay = foundUser.password_expires_day; + const dayInMilliseconds = 24 * 60 * 60 * 1000; + console.log( + 'exp : ', + passwordExpiryDate, + passwordExpiryDay, + dayInMilliseconds, + ); + const today = new Date().getTime(); + const comparasionDate = new Date( + passwordExpiryDate.getTime() + passwordExpiryDay * dayInMilliseconds, + ).getTime(); + if (today >= comparasionDate) { + throw new BadRequestException( + 'Password token is expired contact to your admin', + ); + } + + const hashPassword = this.passHandlers.create_hashed_password( + foundUser.uu_id, + dto.password, + ); + + const updatedUser = await this.prisma.users.update({ + where: { id: foundUser.id }, + data: { + hash_password: hashPassword, + password_token: '', + password_expiry_begins: new Date(), + }, + }); + console.log('updatedUser'); + console.dir(updatedUser); + await this.prisma.password_history.create({ + data: { + userUUID: foundUser.uu_id, + password: hashPassword, + old_password_first: dto.password, + old_password_first_modified_at: new Date(), + old_password_second: '', + old_password_second_modified_at: new Date(), + old_password_third: '', + old_password_third_modified_at: new Date(), + }, + }); + return { message: 'Password created successfully' }; } } diff --git a/ServicesApi/src/auth/password/create/dtoValidator.ts b/ServicesApi/src/auth/password/create/dtoValidator.ts new file mode 100644 index 0000000..328ea21 --- /dev/null +++ b/ServicesApi/src/auth/password/create/dtoValidator.ts @@ -0,0 +1,12 @@ +import { IsString } from 'class-validator'; + +export class userCreatePasswordValidator { + @IsString() + passwordToken: string; + + @IsString() + password: string; + + @IsString() + rePassword: string; +} diff --git a/ServicesApi/src/auth/password/reset/dtoValidator.ts b/ServicesApi/src/auth/password/reset/dtoValidator.ts new file mode 100644 index 0000000..71f38f1 --- /dev/null +++ b/ServicesApi/src/auth/password/reset/dtoValidator.ts @@ -0,0 +1,6 @@ +import { IsString } from 'class-validator'; + +export class userResetPasswordValidator { + @IsString() + accessKey: string; +} diff --git a/ServicesApi/src/auth/password/reset/reset.service.ts b/ServicesApi/src/auth/password/reset/reset.service.ts index e3c0c00..3cfccf5 100644 --- a/ServicesApi/src/auth/password/reset/reset.service.ts +++ b/ServicesApi/src/auth/password/reset/reset.service.ts @@ -1,8 +1,36 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, BadRequestException } from '@nestjs/common'; +import { userResetPasswordValidator } from './dtoValidator'; +import { PrismaService } from '@/src/prisma.service'; +import { PasswordHandlers } from '@/src/utils/auth/login_handler'; @Injectable() export class ResetPasswordService { - async run(dto: any) { - return dto; + constructor( + private readonly prisma: PrismaService, + private readonly passHandlers: PasswordHandlers, + ) {} + async run(dto: userResetPasswordValidator) { + const foundUser = await this.prisma.users.findFirstOrThrow({ + where: { + OR: [{ email: dto.accessKey }, { phone_number: dto.accessKey }], + }, + }); + if (!foundUser) { + throw new BadRequestException( + 'User not found. Please check your email or phone number', + ); + } + + await this.prisma.users.update({ + where: { id: foundUser.id }, + data: { + password_token: this.passHandlers.generateRefreshToken(), + password_expiry_begins: new Date(), + password_expires_day: 30, + }, + }); + return { + message: 'Password reset token sent successfully', + }; } } diff --git a/ServicesApi/src/auth/password/verify-otp/dtoValidator.ts b/ServicesApi/src/auth/password/verify-otp/dtoValidator.ts new file mode 100644 index 0000000..0e43f97 --- /dev/null +++ b/ServicesApi/src/auth/password/verify-otp/dtoValidator.ts @@ -0,0 +1,8 @@ +import { IsNumber, Max, Min } from 'class-validator'; + +export class userVerifyOtpValidator { + @IsNumber() + @Min(6) + @Max(6) + otp: number; +} diff --git a/ServicesApi/src/auth/password/verify-otp/verify-otp.service.ts b/ServicesApi/src/auth/password/verify-otp/verify-otp.service.ts index 30ba47d..bcaed97 100644 --- a/ServicesApi/src/auth/password/verify-otp/verify-otp.service.ts +++ b/ServicesApi/src/auth/password/verify-otp/verify-otp.service.ts @@ -1,7 +1,26 @@ import { Injectable } from '@nestjs/common'; +import { authenticator } from 'otplib'; +import * as qrcode from 'qrcode'; +import { PrismaService } from '@/src/prisma.service'; @Injectable() export class VerifyOtpService { + constructor(private readonly prisma: PrismaService) {} + generate2FASecret(username: string) { + const serviceName = 'BenimUygulamam'; + const secret = authenticator.generateSecret(); + const otpauthUrl = authenticator.keyuri(username, serviceName, secret); + return { secret, otpauthUrl }; + } + + async generateQRCode(otpauthUrl: string): Promise { + return await qrcode.toDataURL(otpauthUrl); + } + + verify2FACode(code: string, secret: string): boolean { + return authenticator.verify({ token: code, secret }); + } + async run(dto: any) { return dto; } diff --git a/ServicesApi/src/middleware/access-control.guard.ts b/ServicesApi/src/middleware/access-control.guard.ts index 40308d9..0cce8ba 100644 --- a/ServicesApi/src/middleware/access-control.guard.ts +++ b/ServicesApi/src/middleware/access-control.guard.ts @@ -6,30 +6,13 @@ import { } from '@nestjs/common'; import { RedisHandlers } from '@/src/utils/auth/redis_handlers'; -const getAccessTokenFromHeader = (req: Request): string => { - console.log(req.headers); - const token = req.headers['acs']; - if (!token) { - throw new ForbiddenException('Access token header is missing'); - } - return token; -}; - -const getSelectTokenFromHeader = (req: Request): string => { - const token = req.headers['slc']; - if (!token) { - throw new ForbiddenException('Select token header is missing'); - } - return token; -}; - @Injectable() export class AuthControlGuard implements CanActivate { constructor(private cacheService: RedisHandlers) {} async canActivate(context: ExecutionContext): Promise { const req = context.switchToHttp().getRequest(); - const accessToken = getAccessTokenFromHeader(req); + const accessToken = this.cacheService.mergeLoginKey(req); console.log('AuthControlGuard', accessToken); // const hasAccess = accessObject.permissions?.some( // (p: any) => p.method === method && p.url === path, @@ -49,7 +32,7 @@ export class EndpointControlGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const req = context.switchToHttp().getRequest(); - const selectToken = getSelectTokenFromHeader(req); + const selectToken = this.cacheService.mergeSelectKey(req); const method = req.method; const path = req.route?.path; console.log('EndpointControlGuard', selectToken, method, path); diff --git a/ServicesApi/src/utils/auth/login_handler.ts b/ServicesApi/src/utils/auth/login_handler.ts index 81c39b5..a681162 100644 --- a/ServicesApi/src/utils/auth/login_handler.ts +++ b/ServicesApi/src/utils/auth/login_handler.ts @@ -18,7 +18,6 @@ class PasswordHandlers { create_hashed_password(uuid: string, password: string): string { const data = `${uuid}:${password}`; - console.log(crypto.createHash('sha256').update(data).digest('hex')); return crypto.createHash('sha256').update(data).digest('hex'); } @@ -33,7 +32,6 @@ class PasswordHandlers { hashed_password: string, ): boolean { const created_hashed_password = this.create_hashed_password(uuid, password); - console.log('created_hashed_password', created_hashed_password); return created_hashed_password === hashed_password; } diff --git a/ServicesApi/src/utils/auth/redis_handlers.ts b/ServicesApi/src/utils/auth/redis_handlers.ts index 7ec6d7c..9e7e93d 100644 --- a/ServicesApi/src/utils/auth/redis_handlers.ts +++ b/ServicesApi/src/utils/auth/redis_handlers.ts @@ -7,7 +7,17 @@ import { import { CacheService } from '@/src/cache.service'; import { users } from '@prisma/client'; import { PasswordHandlers } from './login_handler'; -import { Injectable } from '@nestjs/common'; +import { Injectable, ForbiddenException } from '@nestjs/common'; + +interface LoginFromRedis { + key: string; + value: AuthToken; +} + +interface SelectFromRedis { + key: string; + value: TokenDictInterface; +} @Injectable() export class RedisHandlers { @@ -17,6 +27,50 @@ export class RedisHandlers { private readonly passwordService: PasswordHandlers, ) {} + /** + * Validates that a Redis key follows the expected format + * Format: AUTH_TOKEN:token:token:UUID or AUTH_TOKEN:token:token:*:* + this.AUTH_TOKEN:token:token:UUID:UUID + */ + private validateRedisKey(redisKey: string): boolean { + if (!redisKey.startsWith(this.AUTH_TOKEN + ':')) { + throw new ForbiddenException( + `Invalid Redis key format. Must start with ${this.AUTH_TOKEN}:`, + ); + } + const colonCount = (redisKey.match(/:/g) || []).length; + if (colonCount !== 4) { + throw new ForbiddenException( + `Invalid Redis key format. Must have exactly 5 colons. Found: ${colonCount}`, + ); + } + return true; + } + + public mergeLoginKey(req: Request): string { + const acsToken = req.headers['acs']; + if (!acsToken) { + throw new ForbiddenException('Access token header is missing'); + } + const mergedRedisKey = `${this.AUTH_TOKEN}:${acsToken}:${acsToken}:*:*`; + this.validateRedisKey(mergedRedisKey); + return mergedRedisKey; + } + + public mergeSelectKey(req: Request): string { + const acsToken = req.headers['acs']; + if (!acsToken) { + throw new ForbiddenException('Access token header is missing'); + } + const slcToken = req.headers['slc']; + if (!slcToken) { + throw new ForbiddenException('Select token header is missing'); + } + const mergedRedisKey = `${this.AUTH_TOKEN}:${acsToken}:${slcToken}:*:*`; + this.validateRedisKey(mergedRedisKey); + return mergedRedisKey; + } + generateSelectToken(accessToken: string, userUUID: string) { return this.passwordService.createSelectToken(accessToken, userUUID); } @@ -25,22 +79,97 @@ export class RedisHandlers { return this.passwordService.generateAccessToken(); } - async getLoginFromRedis(redisKey: string): Promise { - return this.cacheService.get(redisKey); + private async scanKeys(pattern: string): Promise { + this.validateRedisKey(pattern); + const client = (this.cacheService as any).client; + if (!client) throw new Error('Redis client not available'); + + const keys: string[] = []; + let cursor = '0'; + + do { + const [nextCursor, matchedKeys] = await client.scan( + cursor, + 'MATCH', + pattern, + ); + cursor = nextCursor; + keys.push(...matchedKeys); + } while (cursor !== '0'); + + return keys; } - async getSelectFromRedis(redisKey: string): Promise { - return this.cacheService.get(redisKey); + async getLoginFromRedis(req: Request): Promise { + const mergedKey = this.mergeLoginKey(req); + if (mergedKey.includes('*')) { + const keys = await this.scanKeys(mergedKey); + if (keys.length === 0) { + throw new ForbiddenException('Authorization failed - No matching keys'); + } + for (const key of keys) { + const parts = key.split(':'); + if (parts.length >= 3) { + if (parts[1] === parts[2]) { + const value = await this.cacheService.get(key); + if (value) { + return { key, value }; + } + } + } + } + throw new ForbiddenException('Authorization failed - No valid keys'); + } + + const value = await this.cacheService.get(mergedKey); + return value ? { key: mergedKey, value } : null; } - async renewTtlLoginFromRedis(redisKey: string): Promise { - const token = await this.getLoginFromRedis(redisKey); - return this.cacheService.set_with_ttl(redisKey, token, 60 * 30); + async getSelectFromRedis(req: Request): Promise { + const mergedKey = this.mergeSelectKey(req); + if (mergedKey.includes('*')) { + const keys = await this.scanKeys(mergedKey); + + if (keys.length === 0) { + throw new ForbiddenException( + 'Authorization failed - No matching select keys', + ); + } + for (const key of keys) { + const value = await this.cacheService.get(key); + if (value) { + return { key, value }; + } + } + throw new ForbiddenException( + 'Authorization failed - No valid select keys', + ); + } + + const value = await this.cacheService.get(mergedKey); + return value ? { key: mergedKey, value } : null; } - async renewTtlSelectFromRedis(redisKey: string): Promise { - const token = await this.getSelectFromRedis(redisKey); - return this.cacheService.set_with_ttl(redisKey, token, 60 * 30); + async deleteLoginFromRedis(req: Request): Promise { + const mergedKey = this.mergeLoginKey(req); + return this.cacheService.delete(mergedKey); + } + + async deleteSelectFromRedis(req: Request): Promise { + const mergedKey = this.mergeSelectKey(req); + return this.cacheService.delete(mergedKey); + } + + async renewTtlLoginFromRedis(req: Request): Promise { + const mergedKey = this.mergeLoginKey(req); + const value = await this.cacheService.get(mergedKey); + return this.cacheService.set_with_ttl(mergedKey, value, 86400); + } + + async renewTtlSelectFromRedis(req: Request): Promise { + const mergedKey = this.mergeSelectKey(req); + const value = await this.cacheService.get(mergedKey); + return this.cacheService.set_with_ttl(mergedKey, value, 60 * 30); } async setLoginToRedis(token: AuthToken, userUUID: string): Promise {