diff --git a/.prettierrc.json b/.prettierrc.json index ad7bd41..ce90b72 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -4,5 +4,9 @@ "printWidth": 120, "semi": true, "tabWidth": 2, - "trailingComma": "es5" + "trailingComma": "es5", + "importOrder": ["", "^@/(.*)$", "^[./]"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "plugins": ["@trivago/prettier-plugin-sort-imports"] } diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..344d2e1 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "streetsidesoftware.code-spell-checker", + "dbaeumer.vscode-eslint", + "orta.vscode-jest", + "firsttris.vscode-jest-runner", + "esbenp.prettier-vscode", + "yoavbls.pretty-ts-errors" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 1547e31..656fd49 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,9 @@ { - "cSpell.words": ["maxlength", "Parens", "pino"] + "cSpell.words": ["maxlength", "Parens", "pino"], + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": "always", + "source.organizeImports": "always" + }, + "typescript.tsdk": "node_modules\\typescript\\lib" } diff --git a/eslint.config.mjs b/eslint.config.mjs index 71b07a3..2df0375 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,10 +1,11 @@ +import { FlatCompat } from "@eslint/eslintrc"; +import js from "@eslint/js"; import typescriptEslint from "@typescript-eslint/eslint-plugin"; -import globals from "globals"; import tsParser from "@typescript-eslint/parser"; +import checkFile from "eslint-plugin-check-file"; +import globals from "globals"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import js from "@eslint/js"; -import { FlatCompat } from "@eslint/eslintrc"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -22,6 +23,7 @@ export default [ { plugins: { "@typescript-eslint": typescriptEslint, + "check-file": checkFile, }, languageOptions: { globals: { @@ -40,6 +42,25 @@ export default [ "@typescript-eslint/prefer-nullish-coalescing": "error", "@typescript-eslint/strict-boolean-expressions": "error", "no-console": "error", + "prefer-template": ["error"], + "prefer-arrow-callback": ["error"], + "func-style": ["error", "expression"], + "prefer-destructuring": ["error", { object: true, array: true }], + "check-file/filename-naming-convention": [ + "error", + { + "**/*.{ts,tsx}": "KEBAB_CASE", + }, + { + ignoreMiddleExtensions: true, + }, + ], + "check-file/folder-naming-convention": [ + "error", + { + "src/**/!^[.*": "KEBAB_CASE", + }, + ], }, }, ]; diff --git a/package.json b/package.json index b972830..182a88a 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "devDependencies": { "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.9.0", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/bcrypt": "^5.0.2", "@types/cors": "^2.8.17", "@types/express": "^4.17.21", @@ -54,6 +55,7 @@ "@typescript-eslint/eslint-plugin": "^8.1.0", "@typescript-eslint/parser": "^8.1.0", "eslint": "^9.9.0", + "eslint-plugin-check-file": "^2.8.0", "globals": "^15.9.0", "husky": "^9.1.4", "jest": "^29.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0db280a..3b42fbb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,6 +60,9 @@ importers: '@eslint/js': specifier: ^9.9.0 version: 9.9.0 + '@trivago/prettier-plugin-sort-imports': + specifier: ^4.3.0 + version: 4.3.0(prettier@3.3.3) '@types/bcrypt': specifier: ^5.0.2 version: 5.0.2 @@ -93,6 +96,9 @@ importers: eslint: specifier: ^9.9.0 version: 9.9.0 + eslint-plugin-check-file: + specifier: ^2.8.0 + version: 2.8.0(eslint@9.9.0) globals: specifier: ^15.9.0 version: 15.9.0 @@ -148,6 +154,10 @@ packages: resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} engines: {node: '>=6.9.0'} + '@babel/generator@7.17.7': + resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.25.0': resolution: {integrity: sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==} engines: {node: '>=6.9.0'} @@ -156,6 +166,18 @@ packages: resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} engines: {node: '>=6.9.0'} + '@babel/helper-environment-visitor@7.24.7': + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-function-name@7.24.7': + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-hoist-variables@7.24.7': + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.24.7': resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} engines: {node: '>=6.9.0'} @@ -174,6 +196,10 @@ packages: resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} engines: {node: '>=6.9.0'} + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.24.8': resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} engines: {node: '>=6.9.0'} @@ -294,10 +320,18 @@ packages: resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.23.2': + resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.25.3': resolution: {integrity: sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==} engines: {node: '>=6.9.0'} + '@babel/types@7.17.0': + resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} + engines: {node: '>=6.9.0'} + '@babel/types@7.25.2': resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==} engines: {node: '>=6.9.0'} @@ -466,6 +500,15 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@trivago/prettier-plugin-sort-imports@4.3.0': + resolution: {integrity: sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==} + peerDependencies: + '@vue/compiler-sfc': 3.x + prettier: 2.x - 3.x + peerDependenciesMeta: + '@vue/compiler-sfc': + optional: true + '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -1123,6 +1166,12 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + eslint-plugin-check-file@2.8.0: + resolution: {integrity: sha512-FvvafMTam2WJYH9uj+FuMxQ1y+7jY3Z6P9T4j2214cH0FBxNzTcmeCiGTj1Lxp3mI6kbbgsXvmgewvf+llKYyw==} + engines: {node: '>=18'} + peerDependencies: + eslint: '>=7.28.0' + eslint-scope@8.0.2: resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1559,6 +1608,9 @@ packages: engines: {node: '>=10'} hasBin: true + javascript-natural-sort@0.7.1: + resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1804,6 +1856,9 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + log-update@6.1.0: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} @@ -2381,6 +2436,10 @@ packages: source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -2747,6 +2806,12 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/generator@7.17.7': + dependencies: + '@babel/types': 7.25.2 + jsesc: 2.5.2 + source-map: 0.5.7 + '@babel/generator@7.25.0': dependencies: '@babel/types': 7.25.2 @@ -2762,6 +2827,19 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-environment-visitor@7.24.7': + dependencies: + '@babel/types': 7.25.2 + + '@babel/helper-function-name@7.24.7': + dependencies: + '@babel/template': 7.25.0 + '@babel/types': 7.25.2 + + '@babel/helper-hoist-variables@7.24.7': + dependencies: + '@babel/types': 7.25.2 + '@babel/helper-module-imports@7.24.7': dependencies: '@babel/traverse': 7.25.3 @@ -2788,6 +2866,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.25.2 + '@babel/helper-string-parser@7.24.8': {} '@babel/helper-validator-identifier@7.24.7': {} @@ -2901,6 +2983,21 @@ snapshots: '@babel/parser': 7.25.3 '@babel/types': 7.25.2 + '@babel/traverse@7.23.2': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.0 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.25.3 + '@babel/types': 7.25.2 + debug: 4.3.6(supports-color@5.5.0) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + '@babel/traverse@7.25.3': dependencies: '@babel/code-frame': 7.24.7 @@ -2913,6 +3010,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/types@7.17.0': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + '@babel/types@7.25.2': dependencies: '@babel/helper-string-parser': 7.24.8 @@ -3197,6 +3299,18 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.3.3)': + dependencies: + '@babel/generator': 7.17.7 + '@babel/parser': 7.25.3 + '@babel/traverse': 7.23.2 + '@babel/types': 7.17.0 + javascript-natural-sort: 0.7.1 + lodash: 4.17.21 + prettier: 3.3.3 + transitivePeerDependencies: + - supports-color + '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -3892,6 +4006,12 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-plugin-check-file@2.8.0(eslint@9.9.0): + dependencies: + eslint: 9.9.0 + is-glob: 4.0.3 + micromatch: 4.0.7 + eslint-scope@8.0.2: dependencies: esrecurse: 4.3.0 @@ -4376,6 +4496,8 @@ snapshots: filelist: 1.0.4 minimatch: 3.1.2 + javascript-natural-sort@0.7.1: {} + jest-changed-files@29.7.0: dependencies: execa: 5.1.1 @@ -4804,6 +4926,8 @@ snapshots: lodash.once@4.1.1: {} + lodash@4.17.21: {} + log-update@6.1.0: dependencies: ansi-escapes: 7.0.0 @@ -5345,6 +5469,8 @@ snapshots: buffer-from: 1.1.2 source-map: 0.6.1 + source-map@0.5.7: {} + source-map@0.6.1: {} sparse-bitfield@3.0.3: diff --git a/src/api/v1/auth/__test__/auth.test.ts b/src/api/v1/auth/__test__/auth.test.ts index b350219..7193a74 100644 --- a/src/api/v1/auth/__test__/auth.test.ts +++ b/src/api/v1/auth/__test__/auth.test.ts @@ -1,5 +1,8 @@ import { sign } from "jsonwebtoken"; -import { envConstants, errorMap, ErrorTypeEnum, STATUS_CODES } from "@/constants"; +import { ZodError, ZodIssue } from "zod"; + +import { Login, loginSchema } from "@/api/v1/auth/auth.validation"; +import { ErrorTypeEnum, STATUS_CODES, envConstants, errorMap } from "@/constants"; import { expectSignUpSuccess, expectUnauthorizedResponseForInvalidToken, @@ -7,8 +10,6 @@ import { renewToken, signUp, } from "@/utils/test"; -import { Login, loginSchema } from "@/api/v1/auth/auth.validation"; -import { ZodError, ZodIssue } from "zod"; const VALID_CREDENTIALS = { username: "validUser", diff --git a/src/api/v1/auth/__test__/forget-password.test.ts b/src/api/v1/auth/__test__/forget-password.test.ts index f71fb93..2206679 100644 --- a/src/api/v1/auth/__test__/forget-password.test.ts +++ b/src/api/v1/auth/__test__/forget-password.test.ts @@ -1,10 +1,10 @@ +import { defaultUsers } from "@/constants"; import { expectBadRequestResponseForValidationError, expectForgetPasswordSuccess, expectUserNotFoundError, forgetPassword, } from "@/utils/test"; -import { defaultUsers } from "@/constants"; describe("Forget Password", () => { it("should throw error if email is not provided", async () => { diff --git a/src/api/v1/auth/__test__/reset-password.test.ts b/src/api/v1/auth/__test__/reset-password.test.ts index 59b4724..6906113 100644 --- a/src/api/v1/auth/__test__/reset-password.test.ts +++ b/src/api/v1/auth/__test__/reset-password.test.ts @@ -1,3 +1,5 @@ +import { Response } from "supertest"; + import { expectBadRequestResponseForValidationError, expectFindUserByUsernameSuccess, @@ -16,7 +18,7 @@ import { verifyAccount, verifyOTP, } from "@/utils/test"; -import { Response } from "supertest"; + import { GetUser } from "../../user/user.validation"; const user = { diff --git a/src/api/v1/auth/auth.controller.ts b/src/api/v1/auth/auth.controller.ts index dacd3e3..7118dd4 100644 --- a/src/api/v1/auth/auth.controller.ts +++ b/src/api/v1/auth/auth.controller.ts @@ -1,10 +1,12 @@ import { NextFunction, Request, Response } from "express"; -import { success } from "./auth.constant"; + +import { STATUS_CODES, envConstants } from "@/constants"; +import { GoogleUser } from "@/types/passport-google"; import { sendResponse } from "@/utils"; -import { envConstants, STATUS_CODES } from "@/constants"; + +import { success } from "./auth.constant"; import { AuthService } from "./auth.service"; import { AuthToken } from "./auth.validation"; -import { GoogleUser } from "@/types/passport-google"; export class AuthController { private static setTokenCookies(res: Response, accessToken: string, refreshToken: string) { diff --git a/src/api/v1/auth/auth.modal.ts b/src/api/v1/auth/auth.modal.ts index 10f07c7..ecdd615 100644 --- a/src/api/v1/auth/auth.modal.ts +++ b/src/api/v1/auth/auth.modal.ts @@ -1,4 +1,5 @@ import { Schema, Types, model } from "mongoose"; + import { Auth } from "./auth.validation"; const AuthSchema = new Schema( diff --git a/src/api/v1/auth/auth.route.ts b/src/api/v1/auth/auth.route.ts index eed5c94..3b26b9e 100644 --- a/src/api/v1/auth/auth.route.ts +++ b/src/api/v1/auth/auth.route.ts @@ -1,7 +1,9 @@ import { Router } from "express"; -import { AuthController } from "./auth.controller"; + import { signInWithGoogle, signInWithGoogleCallback, validateAccessToken, validateRefreshToken } from "@/middlewares"; +import { AuthController } from "./auth.controller"; + const router = Router(); router.post("/auth/sign-up", AuthController.signUp); diff --git a/src/api/v1/auth/auth.service.ts b/src/api/v1/auth/auth.service.ts index 026d714..8367ed5 100644 --- a/src/api/v1/auth/auth.service.ts +++ b/src/api/v1/auth/auth.service.ts @@ -1,5 +1,5 @@ -import { ErrorTypeEnum } from "@/constants"; -import { comparePassword, generateAccessToken, generateRefreshToken, validateObjectId } from "@/utils"; +import { OtpService } from "@/api/v1/otp/otp.service"; +import { TokenAction, TokenService } from "@/api/v1/token"; import { UserDAL } from "@/api/v1/user/user.dal"; import { UserService } from "@/api/v1/user/user.service"; import { @@ -9,12 +9,13 @@ import { validateEmail, validateResetPasswordSchema, } from "@/api/v1/user/user.validation"; -import { AuthDAL } from "./auth.dal"; -import { loginSchema, Login, AuthToken, Auth } from "./auth.validation"; -import { OtpService } from "@/api/v1/otp/otp.service"; -import { GoogleUser } from "@/types/passport-google"; -import { TokenAction, TokenService } from "@/api/v1/token"; +import { ErrorTypeEnum } from "@/constants"; import { notificationService } from "@/services"; +import { GoogleUser } from "@/types/passport-google"; +import { comparePassword, generateAccessToken, generateRefreshToken, validateObjectId } from "@/utils"; + +import { AuthDAL } from "./auth.dal"; +import { Auth, AuthToken, Login, loginSchema } from "./auth.validation"; export class AuthService { public static async signUp(userData: CreateUser) { @@ -46,14 +47,14 @@ export class AuthService { public static async signInWithGoogle(googleUser: GoogleUser): Promise { const { id: googleId, emails, name } = googleUser; - const primaryEmail = emails[0]; + const [{ value, verified }] = emails; - if (!primaryEmail?.value) { + if (value === null || value === undefined) { throw new Error("Email not provided by Google authentication"); } - const email = primaryEmail.value; - const isEmailVerified = primaryEmail.verified; + const email = value; + const isEmailVerified = verified; // Check if the user exists by Google ID let userRecord = await UserService.getUserByGoogleId(googleId); diff --git a/src/api/v1/auth/auth.validation.ts b/src/api/v1/auth/auth.validation.ts index d59683f..8208f43 100644 --- a/src/api/v1/auth/auth.validation.ts +++ b/src/api/v1/auth/auth.validation.ts @@ -1,7 +1,8 @@ import { z } from "zod"; -import { userSchema } from "../user/user.validation"; + import { otp } from "../otp/otp.validation"; import { tokenSchema } from "../token/token.validation"; +import { userSchema } from "../user/user.validation"; const AuthSchema = z.object({ userId: z.string().regex(/^[a-f\d]{24}$/i, "Invalid id"), diff --git a/src/api/v1/otp/__test__/otp.validation.test.ts b/src/api/v1/otp/__test__/otp.validation.test.ts index 97d458a..08b8b36 100644 --- a/src/api/v1/otp/__test__/otp.validation.test.ts +++ b/src/api/v1/otp/__test__/otp.validation.test.ts @@ -1,4 +1,5 @@ import { ZodError } from "zod"; + import { OtpEvent, otpEvent } from "../otp.validation"; describe("Test OTP validation", () => { diff --git a/src/api/v1/otp/otp.controller.ts b/src/api/v1/otp/otp.controller.ts index 187d51f..dd182fa 100644 --- a/src/api/v1/otp/otp.controller.ts +++ b/src/api/v1/otp/otp.controller.ts @@ -1,7 +1,9 @@ import { NextFunction, Request, Response } from "express"; -import { OtpService } from "./otp.service"; -import { sendResponse } from "@/utils"; + import { STATUS_CODES } from "@/constants"; +import { sendResponse } from "@/utils"; + +import { OtpService } from "./otp.service"; export class OtpController { public static async sendOtp(req: Request, res: Response, next: NextFunction) { diff --git a/src/api/v1/otp/otp.modal.ts b/src/api/v1/otp/otp.modal.ts index 6720b10..0a7be3e 100644 --- a/src/api/v1/otp/otp.modal.ts +++ b/src/api/v1/otp/otp.modal.ts @@ -1,16 +1,21 @@ -import { model, Schema } from "mongoose"; +import { Schema, Types, model } from "mongoose"; + import { OtpSchema } from "./otp.validation"; -const OtpSchema = new Schema( +const OtpSchemas = new Schema( { otp: { type: String, required: true, }, userId: { - type: Schema.Types.ObjectId, - ref: "User", + type: String, required: true, + validate: { + validator: (v: string) => Types.ObjectId.isValid(v), + message: "userId must be a valid MongoDB ObjectId string", + }, + ref: "User", }, expiryTime: { type: Date, @@ -24,4 +29,4 @@ const OtpSchema = new Schema( { timestamps: true } ); -export const OtpModel = model("Otp", OtpSchema); +export const OtpModel = model("Otp", OtpSchemas); diff --git a/src/api/v1/otp/otp.route.ts b/src/api/v1/otp/otp.route.ts index df3929e..e30e5fe 100644 --- a/src/api/v1/otp/otp.route.ts +++ b/src/api/v1/otp/otp.route.ts @@ -1,4 +1,5 @@ import { Router } from "express"; + import { OtpController } from "./otp.controller"; const router = Router(); diff --git a/src/api/v1/otp/otp.service.ts b/src/api/v1/otp/otp.service.ts index 191b330..c78ffa9 100644 --- a/src/api/v1/otp/otp.service.ts +++ b/src/api/v1/otp/otp.service.ts @@ -1,14 +1,15 @@ import { isPast } from "date-fns"; -import { envConstants, ErrorTypeEnum, FIVE_MINUTES_IN_MS } from "@/constants"; -import { generateOTP, verifyOTP } from "@/utils"; import { success } from "@/api/v1/auth/auth.constant"; import { UserService } from "@/api/v1/user/user.service"; -import { OtpDAL } from "./otp.dal"; -import { GetOtp, OtpEvent, otpEvent, OtpSchema, OtpVerifyEvent, otpVerifyEvent } from "./otp.validation"; +import { ErrorTypeEnum, FIVE_MINUTES_IN_MS, envConstants } from "@/constants"; import { notificationService } from "@/services/notification.services"; +import { generateOTP, verifyOTP } from "@/utils"; + import { TokenService } from "../token/token.service"; import { TokenAction } from "../token/token.validation"; +import { OtpDAL } from "./otp.dal"; +import { GetOtp, OtpEvent, OtpSchema, OtpVerifyEvent, otpEvent, otpVerifyEvent } from "./otp.validation"; export class OtpService { public static async sendOtp(otpEvents: OtpEvent): Promise<{ message: string }> { diff --git a/src/api/v1/otp/otp.validation.ts b/src/api/v1/otp/otp.validation.ts index ccef295..7e6a7b6 100644 --- a/src/api/v1/otp/otp.validation.ts +++ b/src/api/v1/otp/otp.validation.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + import { userSchema, validateEmail } from "@/api/v1/user/user.validation"; const otpType = z.enum(["sendEmailVerificationOTP", "verifyPhoneNumber", "sendForgetPasswordOTP"]); diff --git a/src/api/v1/permission/__test__/permission.test.ts b/src/api/v1/permission/__test__/permission.test.ts index 3d63ecb..33f9645 100644 --- a/src/api/v1/permission/__test__/permission.test.ts +++ b/src/api/v1/permission/__test__/permission.test.ts @@ -1,5 +1,4 @@ import { ErrorTypeEnum, STATUS_CODES, errorMap } from "@/constants"; -import { createPermission, PermissionCategory } from "../permission.validation"; import { createPermissionRequest, expectCreatePermissionSuccess, @@ -7,6 +6,8 @@ import { getPermissions, } from "@/utils/test"; +import { PermissionCategory, createPermission } from "../permission.validation"; + const VALID_PERMISSION: createPermission = { name: "create-permission", description: "this is crete permission creating first time", diff --git a/src/api/v1/permission/permission.controller.ts b/src/api/v1/permission/permission.controller.ts index ba989c1..9af765d 100644 --- a/src/api/v1/permission/permission.controller.ts +++ b/src/api/v1/permission/permission.controller.ts @@ -1,6 +1,8 @@ import { NextFunction, Request, Response } from "express"; -import { sendResponse } from "@/utils"; + import { STATUS_CODES } from "@/constants"; +import { sendResponse } from "@/utils"; + import { success } from "./permission.constant"; import { PermissionService } from "./permission.service"; diff --git a/src/api/v1/permission/permission.model.ts b/src/api/v1/permission/permission.model.ts index 7ae264a..98194ce 100644 --- a/src/api/v1/permission/permission.model.ts +++ b/src/api/v1/permission/permission.model.ts @@ -1,4 +1,5 @@ import { Model, Schema, Types, model } from "mongoose"; + import { Permission, PermissionCategory } from "./permission.validation"; const PermissionSchema: Schema = new Schema( diff --git a/src/api/v1/permission/permission.route.ts b/src/api/v1/permission/permission.route.ts index bdc376f..e399f6c 100644 --- a/src/api/v1/permission/permission.route.ts +++ b/src/api/v1/permission/permission.route.ts @@ -1,4 +1,5 @@ import { Router } from "express"; + import { createPermission, getPermissions } from "./permission.controller"; const router = Router(); diff --git a/src/api/v1/permission/permission.service.ts b/src/api/v1/permission/permission.service.ts index edff1f5..b199087 100644 --- a/src/api/v1/permission/permission.service.ts +++ b/src/api/v1/permission/permission.service.ts @@ -1,7 +1,8 @@ -import { createPermission, createPermissionSchema, getPermission } from "./permission.validation"; import { ErrorTypeEnum } from "@/constants"; + import { PermissionDAL } from "./permission.dal"; import { PermissionDto } from "./permission.dto"; +import { createPermission, createPermissionSchema, getPermission } from "./permission.validation"; export class PermissionService { static async createPermission(createPermission: createPermission): Promise { diff --git a/src/api/v1/permission/permission.validation.ts b/src/api/v1/permission/permission.validation.ts index 46227a8..a09c0db 100644 --- a/src/api/v1/permission/permission.validation.ts +++ b/src/api/v1/permission/permission.validation.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + import { objectIdSchema } from "@/utils"; export enum PermissionCategory { diff --git a/src/api/v1/profile/__test__/profle.test.ts b/src/api/v1/profile/__test__/profle.test.ts index eab0f1d..95c18e7 100644 --- a/src/api/v1/profile/__test__/profle.test.ts +++ b/src/api/v1/profile/__test__/profle.test.ts @@ -1,3 +1,4 @@ +import { defaultUsers } from "@/constants"; import { expectBadRequestResponseForValidationError, expectLoginSuccess, @@ -8,7 +9,7 @@ import { login, upSertProfileData, } from "@/utils/test"; -import { defaultUsers } from "@/constants"; + import { CreateProfileData } from "../profile.validation"; const profileData: CreateProfileData = { diff --git a/src/api/v1/profile/profile.controller.ts b/src/api/v1/profile/profile.controller.ts index a311139..f69aef2 100644 --- a/src/api/v1/profile/profile.controller.ts +++ b/src/api/v1/profile/profile.controller.ts @@ -1,7 +1,9 @@ -import { sendResponse } from "@/utils"; import { NextFunction, Request, Response } from "express"; -import { ProfileService } from "./profile.service"; + +import { sendResponse } from "@/utils"; + import { success } from "./profile.constant"; +import { ProfileService } from "./profile.service"; export class ProfileController { static upSertProfile = async (req: Request, res: Response, next: NextFunction) => { diff --git a/src/api/v1/profile/profile.modal.ts b/src/api/v1/profile/profile.modal.ts index 17fdeb8..28cbc94 100644 --- a/src/api/v1/profile/profile.modal.ts +++ b/src/api/v1/profile/profile.modal.ts @@ -1,7 +1,8 @@ -import { model, Schema, Types } from "mongoose"; +import { Schema, Types, model } from "mongoose"; + import { ProfileData } from "./profile.validation"; -const ProfileData = new Schema( +const ProfileSchema = new Schema( { userId: { type: String, @@ -44,4 +45,4 @@ const ProfileData = new Schema( { timestamps: true } ); -export const ProfileDataModel = model("Profile", ProfileData); +export const ProfileDataModel = model("Profile", ProfileSchema); diff --git a/src/api/v1/profile/profile.route.ts b/src/api/v1/profile/profile.route.ts index f8a1561..8befc22 100644 --- a/src/api/v1/profile/profile.route.ts +++ b/src/api/v1/profile/profile.route.ts @@ -1,5 +1,7 @@ import { Router } from "express"; + import { validateAccessToken } from "@/middlewares"; + import { ProfileController } from "./profile.controller"; const router = Router(); diff --git a/src/api/v1/profile/profile.validation.ts b/src/api/v1/profile/profile.validation.ts index fb91122..1ab65eb 100644 --- a/src/api/v1/profile/profile.validation.ts +++ b/src/api/v1/profile/profile.validation.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + import { objectIdSchema } from "@/utils"; export const profileSchema = z.object({ diff --git a/src/api/v1/role/__test__/role.test.ts b/src/api/v1/role/__test__/role.test.ts index 0727db3..c487aab 100644 --- a/src/api/v1/role/__test__/role.test.ts +++ b/src/api/v1/role/__test__/role.test.ts @@ -1,18 +1,19 @@ import { ErrorTypeEnum, STATUS_CODES, defaultUsers, errorMap } from "@/constants"; import { - expectLoginSuccess, - expectSignUpSuccess, - login, - signUp, - verifyAccount, createRoleRequest, expectCreateRoleSuccess, expectGetRolesSuccess, - getRoles, - expectUnauthorizedResponseForMissingAuthorizationHeader, + expectLoginSuccess, + expectSignUpSuccess, expectUnauthorizedResponseForInvalidAuthorizationHeader, + expectUnauthorizedResponseForMissingAuthorizationHeader, expectUnauthorizedResponseWhenUserHasInsufficientPermission, + getRoles, + login, + signUp, + verifyAccount, } from "@/utils/test"; + import { createRole } from "../role.validation"; const VALID_ROLE: createRole = { diff --git a/src/api/v1/role/role.controller.ts b/src/api/v1/role/role.controller.ts index 83a3923..ce82b07 100644 --- a/src/api/v1/role/role.controller.ts +++ b/src/api/v1/role/role.controller.ts @@ -1,8 +1,10 @@ import { NextFunction, Request, Response } from "express"; -import { sendResponse } from "@/utils"; + import { STATUS_CODES } from "@/constants"; -import { RoleService } from "./role.service"; +import { sendResponse } from "@/utils"; + import { success } from "./role.constant"; +import { RoleService } from "./role.service"; export const createRole = async (req: Request, res: Response, next: NextFunction) => { try { diff --git a/src/api/v1/role/role.dal.ts b/src/api/v1/role/role.dal.ts index 327c3a8..17b6c1a 100644 --- a/src/api/v1/role/role.dal.ts +++ b/src/api/v1/role/role.dal.ts @@ -1,5 +1,5 @@ import { RoleModel } from "./role.model"; -import { createRole, Role } from "./role.validation"; +import { Role, createRole } from "./role.validation"; export class RoleDAL { static async createRole(userData: createRole): Promise { diff --git a/src/api/v1/role/role.dto.ts b/src/api/v1/role/role.dto.ts index 1c0ae7e..ffdf02d 100644 --- a/src/api/v1/role/role.dto.ts +++ b/src/api/v1/role/role.dto.ts @@ -1,4 +1,4 @@ -import { getRole, Role } from "./role.validation"; +import { Role, getRole } from "./role.validation"; export const RoleDto = (role: Role) => ({ getRole: (): getRole => { diff --git a/src/api/v1/role/role.model.ts b/src/api/v1/role/role.model.ts index 691d86c..18d7c79 100644 --- a/src/api/v1/role/role.model.ts +++ b/src/api/v1/role/role.model.ts @@ -1,4 +1,5 @@ -import { Schema, model, Model, Types } from "mongoose"; +import { Model, Schema, Types, model } from "mongoose"; + import { Role } from "./role.validation"; const RoleSchema: Schema = new Schema( diff --git a/src/api/v1/role/role.route.ts b/src/api/v1/role/role.route.ts index 8893d82..33906e9 100644 --- a/src/api/v1/role/role.route.ts +++ b/src/api/v1/role/role.route.ts @@ -1,7 +1,9 @@ import { Router } from "express"; -import { createRole, getRoles } from "./role.controller"; + import { checkPermission, validateAccessToken } from "@/middlewares"; +import { createRole, getRoles } from "./role.controller"; + const router = Router(); router.post("/roles", validateAccessToken, checkPermission(["create-roles"]), createRole); diff --git a/src/api/v1/role/role.service.ts b/src/api/v1/role/role.service.ts index 7efa550..ce65207 100644 --- a/src/api/v1/role/role.service.ts +++ b/src/api/v1/role/role.service.ts @@ -1,7 +1,8 @@ +import { ErrorTypeEnum } from "@/constants"; + import { RoleDAL } from "./role.dal"; import { RoleDto } from "./role.dto"; import { createRole, createRoleSchema, getRole } from "./role.validation"; -import { ErrorTypeEnum } from "@/constants"; export class RoleService { static async createRole(userData: createRole): Promise { diff --git a/src/api/v1/role/role.validation.ts b/src/api/v1/role/role.validation.ts index 5b2f9b4..13223cc 100644 --- a/src/api/v1/role/role.validation.ts +++ b/src/api/v1/role/role.validation.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + import { objectIdSchema } from "@/utils"; const roleSchema = z.object({ diff --git a/src/api/v1/rolePermission/__test__/role-permission.test.ts b/src/api/v1/rolePermission/__test__/role-permission.test.ts index 2efe673..7b6bd99 100644 --- a/src/api/v1/rolePermission/__test__/role-permission.test.ts +++ b/src/api/v1/rolePermission/__test__/role-permission.test.ts @@ -1,16 +1,16 @@ +import { PermissionCategory, createPermission } from "@/api/v1/permission/permission.validation"; import { createRole } from "@/api/v1/role/role.validation"; -import { createPermission, PermissionCategory } from "@/api/v1/permission/permission.validation"; +import { defaultUsers } from "@/constants"; import { createPermissionRequest, + createRolePermissionRequest, createRoleRequest, expectCreatePermissionSuccess, + expectCreateRolePermissionSuccess, expectCreateRoleSuccess, expectLoginSuccess, login, - createRolePermissionRequest, - expectCreateRolePermissionSuccess, } from "@/utils/test"; -import { defaultUsers } from "@/constants"; const VALID_ROLE: createRole = { name: "new-role", diff --git a/src/api/v1/rolePermission/role-permission.controller.ts b/src/api/v1/rolePermission/role-permission.controller.ts index a71dc58..21a5f6a 100644 --- a/src/api/v1/rolePermission/role-permission.controller.ts +++ b/src/api/v1/rolePermission/role-permission.controller.ts @@ -1,6 +1,8 @@ import { NextFunction, Request, Response } from "express"; + import { STATUS_CODES } from "@/constants"; import { sendResponse } from "@/utils"; + import { success } from "./role-permission.constant"; import { RolePermissionService } from "./role-permission.service"; diff --git a/src/api/v1/rolePermission/role-permission.model.ts b/src/api/v1/rolePermission/role-permission.model.ts index 667e275..19784b7 100644 --- a/src/api/v1/rolePermission/role-permission.model.ts +++ b/src/api/v1/rolePermission/role-permission.model.ts @@ -1,7 +1,9 @@ import { Schema, model } from "mongoose"; -import { RolePermission } from "./role-permission.validation"; + import { ErrorTypeEnum } from "@/constants"; +import { RolePermission } from "./role-permission.validation"; + const RolePermissionSchema = new Schema( { roleId: { diff --git a/src/api/v1/rolePermission/role-permission.route.ts b/src/api/v1/rolePermission/role-permission.route.ts index 7416f40..8b01df4 100644 --- a/src/api/v1/rolePermission/role-permission.route.ts +++ b/src/api/v1/rolePermission/role-permission.route.ts @@ -1,7 +1,9 @@ import { Router } from "express"; -import { createRolePermission } from "./role-permission.controller"; + import { checkPermission, validateAccessToken } from "@/middlewares"; +import { createRolePermission } from "./role-permission.controller"; + const router = Router(); router.post( diff --git a/src/api/v1/rolePermission/role-permission.service.ts b/src/api/v1/rolePermission/role-permission.service.ts index cda222b..901c48c 100644 --- a/src/api/v1/rolePermission/role-permission.service.ts +++ b/src/api/v1/rolePermission/role-permission.service.ts @@ -1,4 +1,5 @@ import { ErrorTypeEnum } from "@/constants"; + import { RolePermissionDAL } from "./role-permission.dal"; import { RolePermissionDto } from "./role-permission.dto"; import { RolePermission, rolePermissionSchema } from "./role-permission.validation"; diff --git a/src/api/v1/token/token.model.ts b/src/api/v1/token/token.model.ts index 2fb6d97..94c8c58 100644 --- a/src/api/v1/token/token.model.ts +++ b/src/api/v1/token/token.model.ts @@ -1,4 +1,5 @@ -import { model, Model, Schema, Types } from "mongoose"; +import { Model, Schema, Types, model } from "mongoose"; + import { Token, TokenAction } from "./token.validation"; const TokenSchema: Schema = new Schema( diff --git a/src/api/v1/token/token.service.ts b/src/api/v1/token/token.service.ts index 74586a1..99ee7b8 100644 --- a/src/api/v1/token/token.service.ts +++ b/src/api/v1/token/token.service.ts @@ -1,8 +1,10 @@ +import { isPast } from "date-fns"; + +import { ErrorTypeEnum, FIVE_MINUTES_IN_MS } from "@/constants"; import { generateTokenForAction, verifyJWTToken } from "@/utils"; + import { TokenDAL } from "./token.dal"; import { CreateToken, Token, TokenAction } from "./token.validation"; -import { ErrorTypeEnum, FIVE_MINUTES_IN_MS } from "@/constants"; -import { isPast } from "date-fns"; export class TokenService { private tokenDAL: TokenDAL; diff --git a/src/api/v1/token/token.validation.ts b/src/api/v1/token/token.validation.ts index 6a90a6a..5dd2830 100644 --- a/src/api/v1/token/token.validation.ts +++ b/src/api/v1/token/token.validation.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + import { objectIdSchema } from "@/utils"; export enum TokenAction { diff --git a/src/api/v1/user/__test__/password-validation.test.ts b/src/api/v1/user/__test__/password-validation.test.ts index c35f469..2325f06 100644 --- a/src/api/v1/user/__test__/password-validation.test.ts +++ b/src/api/v1/user/__test__/password-validation.test.ts @@ -1,4 +1,5 @@ import { ZodError } from "zod"; + import { password } from "../user.validation"; describe("Password Schema", () => { diff --git a/src/api/v1/user/__test__/restore-user.test.ts b/src/api/v1/user/__test__/restore-user.test.ts index 6de8527..83a066c 100644 --- a/src/api/v1/user/__test__/restore-user.test.ts +++ b/src/api/v1/user/__test__/restore-user.test.ts @@ -1,22 +1,24 @@ +import mongoose from "mongoose"; + import { defaultUsers } from "@/constants"; import { createUser, - expectUserNotFoundError, + expectBadRequestResponseForValidationError, expectFindUserByUsernameSuccess, expectLoginSuccess, + expectRestoreUserSuccess, expectUnauthorizedResponseForInvalidAuthorizationHeader, expectUnauthorizedResponseForMissingAuthorizationHeader, expectUnauthorizedResponseWhenUserHasInsufficientPermission, expectUserCreationSuccess, + expectUserNotFoundError, findUserByUsername, login, - verifyAccount, - expectBadRequestResponseForValidationError, restoreUser, - expectRestoreUserSuccess, + verifyAccount, } from "@/utils/test"; + import { GetUser } from "../user.validation"; -import mongoose from "mongoose"; const newUser = { username: "username", diff --git a/src/api/v1/user/__test__/soft-delete-user.test.ts b/src/api/v1/user/__test__/soft-delete-user.test.ts index e91a51e..80149ce 100644 --- a/src/api/v1/user/__test__/soft-delete-user.test.ts +++ b/src/api/v1/user/__test__/soft-delete-user.test.ts @@ -1,22 +1,24 @@ +import mongoose from "mongoose"; + import { defaultUsers } from "@/constants"; import { createUser, deleteUser, + expectBadRequestResponseForValidationError, expectDeleteUserSuccess, - expectUserNotFoundError, expectFindUserByUsernameSuccess, expectLoginSuccess, expectUnauthorizedResponseForInvalidAuthorizationHeader, expectUnauthorizedResponseForMissingAuthorizationHeader, expectUnauthorizedResponseWhenUserHasInsufficientPermission, expectUserCreationSuccess, + expectUserNotFoundError, findUserByUsername, login, verifyAccount, - expectBadRequestResponseForValidationError, } from "@/utils/test"; + import { GetUser } from "../user.validation"; -import mongoose from "mongoose"; const newUser = { username: "username", diff --git a/src/api/v1/user/__test__/user.test.ts b/src/api/v1/user/__test__/user.test.ts index 4b48080..0148cc4 100644 --- a/src/api/v1/user/__test__/user.test.ts +++ b/src/api/v1/user/__test__/user.test.ts @@ -1,21 +1,23 @@ import supertest from "supertest"; + import { app } from "@/app"; -import { success } from "../user.constant"; import { ErrorTypeEnum, STATUS_CODES, defaultUsers, errorMap } from "@/constants"; import { createUser, - expectUserNotFoundError, expectFindUserByUsernameSuccess, expectLoginSuccess, expectUnauthorizedResponseForInvalidAuthorizationHeader, expectUnauthorizedResponseForMissingAuthorizationHeader, expectUnauthorizedResponseWhenUserHasInsufficientPermission, expectUserCreationSuccess, + expectUserNotFoundError, findUserByUsername, login, verifyAccount, } from "@/utils/test"; +import { success } from "../user.constant"; + const newUser = { username: "username", email: "validemail@example.com", diff --git a/src/api/v1/user/__test__/user.validation.test.ts b/src/api/v1/user/__test__/user.validation.test.ts index 1547b14..894b91c 100644 --- a/src/api/v1/user/__test__/user.validation.test.ts +++ b/src/api/v1/user/__test__/user.validation.test.ts @@ -1,4 +1,4 @@ -import { username, password, validateCreateUser } from "../user.validation"; +import { password, username, validateCreateUser } from "../user.validation"; describe("Username validation", () => { it("should accept valid usernames", () => { diff --git a/src/api/v1/user/user.controller.ts b/src/api/v1/user/user.controller.ts index 41351ce..1950794 100644 --- a/src/api/v1/user/user.controller.ts +++ b/src/api/v1/user/user.controller.ts @@ -1,8 +1,10 @@ import { NextFunction, Request, Response } from "express"; -import { sendResponse } from "@/utils"; + import { STATUS_CODES } from "@/constants"; -import { UserService } from "./user.service"; +import { sendResponse } from "@/utils"; + import { success } from "./user.constant"; +import { UserService } from "./user.service"; export const createUser = async (req: Request, res: Response, next: NextFunction) => { try { diff --git a/src/api/v1/user/user.dal.ts b/src/api/v1/user/user.dal.ts index 1fcd5f1..2f89c5e 100644 --- a/src/api/v1/user/user.dal.ts +++ b/src/api/v1/user/user.dal.ts @@ -1,8 +1,9 @@ import mongoose from "mongoose"; + +import { hashPassword } from "../../../utils"; +import { Login } from "../auth/auth.validation"; import { UserModel } from "./user.model"; import { CreateUser, UpdateUser, User, UserRolePermission } from "./user.validation"; -import { Login } from "../auth/auth.validation"; -import { hashPassword } from "../../../utils"; export class UserDAL { static async createUser(userData: CreateUser): Promise { diff --git a/src/api/v1/user/user.model.ts b/src/api/v1/user/user.model.ts index def83b5..11264ec 100644 --- a/src/api/v1/user/user.model.ts +++ b/src/api/v1/user/user.model.ts @@ -1,7 +1,9 @@ import { Schema, model } from "mongoose"; -import { User } from "./user.validation"; + import { hashPassword } from "@/utils"; +import { User } from "./user.validation"; + const UserSchema = new Schema( { googleId: { type: String }, diff --git a/src/api/v1/user/user.route.ts b/src/api/v1/user/user.route.ts index 787cae3..2e16899 100644 --- a/src/api/v1/user/user.route.ts +++ b/src/api/v1/user/user.route.ts @@ -1,7 +1,9 @@ import { Router } from "express"; -import { createUser, getAllUsers, getUserByUsername, softDeleteUser, restoreUser } from "./user.controller"; + import { checkPermission, validateAccessToken } from "@/middlewares"; +import { createUser, getAllUsers, getUserByUsername, restoreUser, softDeleteUser } from "./user.controller"; + const router = Router(); router.post("/users", validateAccessToken, checkPermission(["create-users"]), createUser); diff --git a/src/api/v1/user/user.service.ts b/src/api/v1/user/user.service.ts index 64ffa3c..7021b9d 100644 --- a/src/api/v1/user/user.service.ts +++ b/src/api/v1/user/user.service.ts @@ -1,18 +1,19 @@ +import { ErrorTypeEnum, ROLES } from "@/constants"; +import { generateRandomUsername, validateObjectId } from "@/utils"; + +import { RoleDAL } from "../role/role.dal"; +import { UserRoleService } from "../userRole/user-role.service"; import { UserDAL } from "./user.dal"; import { UserDto } from "./user.dto"; import { CreateUser, - validateCreateUser, Email, GetUser, UpdateUser, + validateCreateUser, validateEmail, validateUsername, } from "./user.validation"; -import { UserRoleService } from "../userRole/user-role.service"; -import { generateRandomUsername, validateObjectId } from "@/utils"; -import { ErrorTypeEnum, ROLES } from "@/constants"; -import { RoleDAL } from "../role/role.dal"; export class UserService { static async generateUniqueUsername(username: string): Promise { diff --git a/src/api/v1/userRole/__test__/user-role.test.ts b/src/api/v1/userRole/__test__/user-role.test.ts index 591544f..4c72db4 100644 --- a/src/api/v1/userRole/__test__/user-role.test.ts +++ b/src/api/v1/userRole/__test__/user-role.test.ts @@ -1,13 +1,13 @@ +import { createRole } from "@/api/v1/role/role.validation"; +import { defaultUsers } from "@/constants"; import { - expectLoginSuccess, - login, createRoleRequest, - expectCreateRoleSuccess, createUserRoleRequest, + expectCreateRoleSuccess, expectCreateUserRoleSuccess, + expectLoginSuccess, + login, } from "@/utils/test"; -import { createRole } from "@/api/v1/role/role.validation"; -import { defaultUsers } from "@/constants"; const VALID_ROLE: createRole = { name: "new-role", diff --git a/src/api/v1/userRole/user-role.controller.ts b/src/api/v1/userRole/user-role.controller.ts index d628c54..201499f 100644 --- a/src/api/v1/userRole/user-role.controller.ts +++ b/src/api/v1/userRole/user-role.controller.ts @@ -1,6 +1,8 @@ import { NextFunction, Request, Response } from "express"; + import { STATUS_CODES } from "@/constants"; import { sendResponse } from "@/utils"; + import { success } from "./user-role.constant"; import { UserRoleService } from "./user-role.service"; diff --git a/src/api/v1/userRole/user-role.model.ts b/src/api/v1/userRole/user-role.model.ts index 2bdc9c8..de990de 100644 --- a/src/api/v1/userRole/user-role.model.ts +++ b/src/api/v1/userRole/user-role.model.ts @@ -1,7 +1,9 @@ import { Schema, model } from "mongoose"; -import { UserRole } from "./user-role.validation"; + import { ErrorTypeEnum } from "@/constants"; +import { UserRole } from "./user-role.validation"; + const UserRoleSchema = new Schema( { userId: { diff --git a/src/api/v1/userRole/user-role.route.ts b/src/api/v1/userRole/user-role.route.ts index ea2f6f3..dbdb662 100644 --- a/src/api/v1/userRole/user-role.route.ts +++ b/src/api/v1/userRole/user-role.route.ts @@ -1,4 +1,5 @@ import { Router } from "express"; + import { createUserRole } from "./user-role.controller"; const router = Router(); diff --git a/src/api/v1/userRole/user-role.service.ts b/src/api/v1/userRole/user-role.service.ts index d845aa1..70722ee 100644 --- a/src/api/v1/userRole/user-role.service.ts +++ b/src/api/v1/userRole/user-role.service.ts @@ -1,8 +1,9 @@ import { ErrorTypeEnum } from "@/constants"; +import { validateObjectId } from "@/utils"; + import { UserRoleDAL } from "./user-role.dal"; import { UserRoleDto } from "./user-role.dto"; import { UserRole, userRoleSchema } from "./user-role.validation"; -import { validateObjectId } from "@/utils"; export class UserRoleService { static async createUserRole(userRole: UserRole) { diff --git a/src/app.ts b/src/app.ts index 7657ab8..df71eb8 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,14 +1,14 @@ -import express, { Request, Response, NextFunction, type Application } from "express"; -import { pinoHttp } from "pino-http"; -import helmet from "helmet"; import cors from "cors"; -import passport from "passport"; +import express, { type Application, NextFunction, Request, Response } from "express"; import rateLimit from "express-rate-limit"; +import helmet from "helmet"; +import passport from "passport"; +import { pinoHttp } from "pino-http"; -import { envConstants, ErrorTypeEnum, FIFTEEN_MINUTES_IN_MS } from "@/constants"; -import { logger } from "@/utils"; +import { ErrorTypeEnum, FIFTEEN_MINUTES_IN_MS, envConstants } from "@/constants"; import { addAxiosHeadersMiddleware, errorHandler } from "@/middlewares"; import { routes } from "@/routes"; +import { logger } from "@/utils"; import "./config/passport"; diff --git a/src/config/mongodb.ts b/src/config/mongodb.ts index dbfd129..79b6bcc 100644 --- a/src/config/mongodb.ts +++ b/src/config/mongodb.ts @@ -1,5 +1,6 @@ import mongoose from "mongoose"; -import { envConstants, ErrorTypeEnum } from "@/constants"; + +import { ErrorTypeEnum, envConstants } from "@/constants"; import { logger } from "@/utils"; const { DATABASE_URL, NODE_ENV } = envConstants; diff --git a/src/config/passport.ts b/src/config/passport.ts index 101048c..68b5f20 100644 --- a/src/config/passport.ts +++ b/src/config/passport.ts @@ -1,7 +1,8 @@ import passport from "passport"; import { Strategy as GoogleStrategy } from "passport-google-oauth20"; -import { envConstants } from "@/constants"; + import { UserService } from "@/api/v1/user/user.service"; +import { envConstants } from "@/constants"; passport.serializeUser((user, done) => { done(null, user); diff --git a/src/constants/env.constant.ts b/src/constants/env.constant.ts index 3c40ba3..cd951b2 100644 --- a/src/constants/env.constant.ts +++ b/src/constants/env.constant.ts @@ -1,9 +1,10 @@ import dotenv from "dotenv"; -dotenv.config(); - import { z } from "zod"; + import { userSchema } from "@/api/v1/user/user.validation"; +dotenv.config(); + const envSchema = z.object({ DATABASE_URL: z.string().min(1, "DATABASE_URL is required").readonly(), APP_PORT: z.coerce.number().min(1, "APP_PORT is required and must be a number greater than 0").readonly(), diff --git a/src/constants/errorTypes.constant.ts b/src/constants/error-types.constant.ts similarity index 99% rename from src/constants/errorTypes.constant.ts rename to src/constants/error-types.constant.ts index 4e57eed..2fa7143 100644 --- a/src/constants/errorTypes.constant.ts +++ b/src/constants/error-types.constant.ts @@ -1,5 +1,6 @@ import { z } from "zod"; -import { STATUS_CODES } from "./statusCode.constant"; + +import { STATUS_CODES } from "./status-code.constant"; const errorType = [ "VALIDATION_ERROR", diff --git a/src/constants/index.ts b/src/constants/index.ts index 1a5e18f..8f46451 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,5 +1,5 @@ export * from "./env.constant"; -export * from "./errorTypes.constant"; -export * from "./magicNumbers.constant"; -export * from "./statusCode.constant"; +export * from "./error-types.constant"; +export * from "./magic-numbers.constant"; export * from "./rbac.constants"; +export * from "./status-code.constant"; diff --git a/src/constants/magicNumbers.constant.ts b/src/constants/magic-numbers.constant.ts similarity index 100% rename from src/constants/magicNumbers.constant.ts rename to src/constants/magic-numbers.constant.ts diff --git a/src/constants/rbac.constants.ts b/src/constants/rbac.constants.ts index c6ea746..a6cb7ed 100644 --- a/src/constants/rbac.constants.ts +++ b/src/constants/rbac.constants.ts @@ -1,6 +1,8 @@ import { Types } from "mongoose"; -import { createPermission, PermissionCategory } from "@/api/v1/permission/permission.validation"; + +import { PermissionCategory, createPermission } from "@/api/v1/permission/permission.validation"; import { createRole } from "@/api/v1/role/role.validation"; + import { envConstants } from "./env.constant"; // Generate a unique ObjectId for the system user, which might represent a system-level action diff --git a/src/constants/statusCode.constant.ts b/src/constants/status-code.constant.ts similarity index 100% rename from src/constants/statusCode.constant.ts rename to src/constants/status-code.constant.ts diff --git a/src/jest.setup.ts b/src/jest.setup.ts index d330e7b..7bd3cf4 100644 --- a/src/jest.setup.ts +++ b/src/jest.setup.ts @@ -1,7 +1,7 @@ import { connectDB, disconnectDB } from "./config"; -import { startServer, stopServer } from "./server"; import { envConstants } from "./constants"; import { setupInitialRolesAndPermissions, setupInitialUserRole } from "./script"; +import { startServer, stopServer } from "./server"; beforeAll(async () => { await connectDB(); diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts index da1a52b..e1e834a 100644 --- a/src/middlewares/auth.ts +++ b/src/middlewares/auth.ts @@ -1,8 +1,9 @@ -import { NextFunction, Response, Request } from "express"; -import { extractTokenFromBearerString, verifyJWTToken } from "@/utils/jwt.util"; -import { ErrorTypeEnum } from "@/constants"; -import { Auth, JwtAccessToken, JwtRefreshToken } from "@/api/v1/auth/auth.validation"; +import { NextFunction, Request, Response } from "express"; + import { AuthService } from "@/api/v1/auth/auth.service"; +import { Auth, JwtAccessToken, JwtRefreshToken } from "@/api/v1/auth/auth.validation"; +import { ErrorTypeEnum } from "@/constants"; +import { extractTokenFromBearerString, verifyJWTToken } from "@/utils/jwt.util"; const parseUser = async (req: Request, _: Response, next: NextFunction, tokenType: "access" | "refresh") => { try { diff --git a/src/middlewares/axiosHeader.ts b/src/middlewares/axios-header.ts similarity index 99% rename from src/middlewares/axiosHeader.ts rename to src/middlewares/axios-header.ts index 3b05d35..97873e5 100644 --- a/src/middlewares/axiosHeader.ts +++ b/src/middlewares/axios-header.ts @@ -1,5 +1,6 @@ -import { NextFunction, Request, Response } from "express"; import axios from "axios"; +import { NextFunction, Request, Response } from "express"; + import { getServerURL } from "@/utils"; export const addAxiosHeadersMiddleware = (req: Request, _: Response, next: NextFunction) => { diff --git a/src/middlewares/checkPermission.ts b/src/middlewares/check-permission.ts similarity index 92% rename from src/middlewares/checkPermission.ts rename to src/middlewares/check-permission.ts index 3d17715..4e0e492 100644 --- a/src/middlewares/checkPermission.ts +++ b/src/middlewares/check-permission.ts @@ -1,12 +1,13 @@ import { NextFunction, Request, Response } from "express"; -import { ErrorTypeEnum, Permission } from "@/constants"; -import { UserDAL } from "@/api/v1/user/user.dal"; + import { Auth } from "@/api/v1/auth/auth.validation"; +import { UserDAL } from "@/api/v1/user/user.dal"; +import { ErrorTypeEnum, Permission } from "@/constants"; export const checkPermission = (requiredPermissions: Permission[]) => { return async (req: Request, _: Response, next: NextFunction) => { try { - const loggedInUser: Auth = req.body.loggedInUser; + const { loggedInUser } = req.body as { loggedInUser: Auth }; const userRolePermissions = await UserDAL.getUserRolesAndPermissionsByUserId(loggedInUser.userId); diff --git a/src/middlewares/errorHandler.ts b/src/middlewares/error-handler.ts similarity index 94% rename from src/middlewares/errorHandler.ts rename to src/middlewares/error-handler.ts index fa065c5..1641ec0 100644 --- a/src/middlewares/errorHandler.ts +++ b/src/middlewares/error-handler.ts @@ -1,8 +1,9 @@ import { NextFunction, Request, Response } from "express"; -import { ErrorTypeEnum, getErrorObject } from "@/constants"; -import { sendResponse } from "@/utils/sendResponse.util"; import { ZodError } from "zod"; +import { ErrorTypeEnum, getErrorObject } from "@/constants"; +import { sendResponse } from "@/utils/send-response.util"; + export const errorHandler = (err: Error, _: Request, res: Response, next: NextFunction) => { if (err instanceof ZodError) { const errorObj = getErrorObject(ErrorTypeEnum.enum.VALIDATION_ERROR); diff --git a/src/middlewares/index.ts b/src/middlewares/index.ts index 7f1cad2..a73d100 100644 --- a/src/middlewares/index.ts +++ b/src/middlewares/index.ts @@ -1,5 +1,5 @@ export * from "./auth"; -export * from "./errorHandler"; +export * from "./error-handler"; export * from "./passport"; -export * from "./checkPermission"; -export * from "./axiosHeader"; +export * from "./check-permission"; +export * from "./axios-header"; diff --git a/src/middlewares/passport.ts b/src/middlewares/passport.ts index 4ae81f5..3592da9 100644 --- a/src/middlewares/passport.ts +++ b/src/middlewares/passport.ts @@ -1,9 +1,10 @@ import { NextFunction, Request, Response } from "express"; import passport from "passport"; + import { envConstants } from "@/constants"; export const signInWithGoogle = (req: Request, res: Response, next: NextFunction) => { - const redirectUrl = req.query.redirectUrl; + const { redirectUrl } = req.query; const state = typeof redirectUrl === "string" && redirectUrl.length > 0 ? Buffer.from(redirectUrl).toString("base64") : undefined; diff --git a/src/routes/index.ts b/src/routes/index.ts index a2fe4f0..e396752 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,12 +1,13 @@ import { Router } from "express"; -import { userRoutes } from "@/api/v1/user/user.route"; -import { roleRoutes } from "@/api/v1/role/role.route"; -import { permissionRoutes } from "@/api/v1/permission/permission.route"; -import { rolePermissionRoutes } from "@/api/v1/rolePermission/role-permission.route"; + import { authRoutes } from "@/api/v1/auth/auth.route"; -import { userRoleRoutes } from "@/api/v1/userRole/user-role.route"; import { otpRoutes } from "@/api/v1/otp/otp.route"; +import { permissionRoutes } from "@/api/v1/permission/permission.route"; import { profileRoutes } from "@/api/v1/profile/profile.route"; +import { roleRoutes } from "@/api/v1/role/role.route"; +import { rolePermissionRoutes } from "@/api/v1/rolePermission/role-permission.route"; +import { userRoutes } from "@/api/v1/user/user.route"; +import { userRoleRoutes } from "@/api/v1/userRole/user-role.route"; export const routes = Router(); diff --git a/src/script/initialize.ts b/src/script/initialize.ts index 1fd38fc..1d4b4f6 100644 --- a/src/script/initialize.ts +++ b/src/script/initialize.ts @@ -5,10 +5,10 @@ import { RoleService } from "@/api/v1/role/role.service"; import { RolePermissionService } from "@/api/v1/rolePermission/role-permission.service"; import { UserService } from "@/api/v1/user/user.service"; import { UserRoleService } from "@/api/v1/userRole/user-role.service"; -import { defaultPermissions, defaultRolePermissions, defaultRoles, defaultUsers, ROLES } from "@/constants"; +import { ROLES, defaultPermissions, defaultRolePermissions, defaultRoles, defaultUsers } from "@/constants"; import { logger } from "@/utils"; -export async function setupInitialRolesAndPermissions() { +export const setupInitialRolesAndPermissions = async () => { await PermissionDAL.createPermissions(defaultPermissions); await RoleDAL.createRoles(defaultRoles); @@ -44,9 +44,9 @@ export async function setupInitialRolesAndPermissions() { } }); }); -} +}; -export async function setupInitialUserRole() { +export const setupInitialUserRole = async () => { try { const user = await UserService.createUser(defaultUsers); @@ -63,4 +63,4 @@ export async function setupInitialUserRole() { } catch (error) { logger.error(`Error while creating user role: error = ${error}`); } -} +}; diff --git a/src/server.ts b/src/server.ts index 8096a90..dce217f 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,4 +1,5 @@ import http from "http"; + import { app } from "./app"; const server = http.createServer(app); diff --git a/src/services/notification.services.ts b/src/services/notification.services.ts index cd2a43c..4475ad0 100644 --- a/src/services/notification.services.ts +++ b/src/services/notification.services.ts @@ -1,7 +1,9 @@ import axios from "axios"; -import { EmailNotification } from "./notification.validation"; -import { logger } from "@/utils"; + import { envConstants } from "@/constants"; +import { logger } from "@/utils"; + +import { EmailNotification } from "./notification.validation"; const sendEmail = async (body: EmailNotification) => { try { diff --git a/src/utils/__test__/jwt.test.ts b/src/utils/__test__/jwt.test.ts index 5c80494..8c05370 100644 --- a/src/utils/__test__/jwt.test.ts +++ b/src/utils/__test__/jwt.test.ts @@ -1,6 +1,6 @@ import { JwtAccessToken } from "@/api/v1/auth/auth.validation"; -import { extractTokenFromBearerString, generateAccessToken, generateRefreshToken } from "@/utils"; import { ErrorTypeEnum } from "@/constants"; +import { extractTokenFromBearerString, generateAccessToken, generateRefreshToken } from "@/utils"; jest.mock("jsonwebtoken", () => ({ sign: jest.fn(), diff --git a/src/utils/__test__/password.test.ts b/src/utils/__test__/password.test.ts index 460ea65..1d47f62 100644 --- a/src/utils/__test__/password.test.ts +++ b/src/utils/__test__/password.test.ts @@ -1,4 +1,4 @@ -import { hashPassword, comparePassword } from "@/utils"; +import { comparePassword, hashPassword } from "@/utils"; describe("Password Utility", () => { it("should hash a password", async () => { diff --git a/src/utils/__test__/sendResponse.test.ts b/src/utils/__test__/send-response.test.ts similarity index 99% rename from src/utils/__test__/sendResponse.test.ts rename to src/utils/__test__/send-response.test.ts index ab46751..c4cc027 100644 --- a/src/utils/__test__/sendResponse.test.ts +++ b/src/utils/__test__/send-response.test.ts @@ -1,4 +1,5 @@ import { Response } from "express"; + import { SendResponse, sendResponse } from "@/utils"; describe("sendResponse", () => { diff --git a/src/utils/index.ts b/src/utils/index.ts index 787a51d..a0032a2 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,7 +1,7 @@ -export { default as logger } from "./Logger"; +export * from "./helper.util"; export * from "./jwt.util"; +export { default as logger } from "./logger"; export * from "./otp.util"; export * from "./password.util"; -export * from "./sendResponse.util"; -export * from "./helper.util"; +export * from "./send-response.util"; export * from "./validation.util"; diff --git a/src/utils/jwt.util.ts b/src/utils/jwt.util.ts index cbe07a2..0430564 100644 --- a/src/utils/jwt.util.ts +++ b/src/utils/jwt.util.ts @@ -1,14 +1,15 @@ import jwt from "jsonwebtoken"; -import { envConstants, ErrorTypeEnum } from "@/constants"; + +import { AuthDAL } from "@/api/v1/auth/auth.dal"; import { JwtAccessToken, - jwtAccessTokenSchema, JwtActionToken, - jwtActionTokenSchema, JwtRefreshToken, + jwtAccessTokenSchema, + jwtActionTokenSchema, jwtRefreshTokenSchema, } from "@/api/v1/auth/auth.validation"; -import { AuthDAL } from "@/api/v1/auth/auth.dal"; +import { ErrorTypeEnum, envConstants } from "@/constants"; const { JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, JWT_TOKEN_FOR_ACTION_SECRET } = envConstants; diff --git a/src/utils/Logger.ts b/src/utils/logger.ts similarity index 99% rename from src/utils/Logger.ts rename to src/utils/logger.ts index 4930638..8d7f4e7 100644 --- a/src/utils/Logger.ts +++ b/src/utils/logger.ts @@ -1,6 +1,7 @@ +import fs from "fs"; import path from "path"; import pino, { type DestinationStream } from "pino"; -import fs from "fs"; + import { envConstants } from "@/constants"; // Define the log directory path diff --git a/src/utils/otp.util.ts b/src/utils/otp.util.ts index 362fed7..81275ae 100644 --- a/src/utils/otp.util.ts +++ b/src/utils/otp.util.ts @@ -5,6 +5,6 @@ export const generateOTP = (length: number = 6): OTP => { return Math.floor(factor + Math.random() * 9 * factor).toString(); }; -export const verifyOTP = (otp: OTP, input: OTP) => { +export const verifyOTP = (otp: OTP, input: OTP): boolean => { return otp === input; }; diff --git a/src/utils/password.util.ts b/src/utils/password.util.ts index 7527f89..1a416a4 100644 --- a/src/utils/password.util.ts +++ b/src/utils/password.util.ts @@ -1,11 +1,11 @@ import * as bcrypt from "bcrypt"; -export async function hashPassword(password: string): Promise { +export const hashPassword = async (password: string): Promise => { const saltRounds = 10; const salt = await bcrypt.genSalt(saltRounds); return bcrypt.hash(password, salt); -} +}; -export async function comparePassword(password: string, hashedPassword: string): Promise { +export const comparePassword = async (password: string, hashedPassword: string): Promise => { return await bcrypt.compare(password, hashedPassword); -} +}; diff --git a/src/utils/sendResponse.util.ts b/src/utils/send-response.util.ts similarity index 95% rename from src/utils/sendResponse.util.ts rename to src/utils/send-response.util.ts index 2ab31a1..a4edb5c 100644 --- a/src/utils/sendResponse.util.ts +++ b/src/utils/send-response.util.ts @@ -1,7 +1,9 @@ import { Response, request } from "express"; -import { errorLogger } from "./Logger"; + import { envConstants } from "@/constants"; +import { errorLogger } from "./logger"; + export interface SendResponse { response: Response; statusCode: number; diff --git a/src/utils/test/auth.utils.ts b/src/utils/test/auth.utils.ts index 826de76..751a2cd 100644 --- a/src/utils/test/auth.utils.ts +++ b/src/utils/test/auth.utils.ts @@ -1,17 +1,19 @@ import supertest, { Response } from "supertest"; -import { app } from "@/app"; -import { Login } from "@/api/v1/auth/auth.validation"; -import { errorMap, ErrorTypeEnum, STATUS_CODES } from "@/constants"; + import { success } from "@/api/v1/auth/auth.constant"; +import { Login } from "@/api/v1/auth/auth.validation"; +import { app } from "@/app"; +import { ErrorTypeEnum, STATUS_CODES, errorMap } from "@/constants"; + +import { CreateUser, ResetPassword } from "../../api/v1/user/user.validation"; import { expectOTPRequestSuccess, expectOTPVerificationSuccess, requestOTP, retrieveOTP, verifyOTP } from "./otp.utils"; import { expectFindUserByUsernameSuccess, findUserByUsername } from "./user.utils"; -import { CreateUser, ResetPassword } from "../../api/v1/user/user.validation"; -export async function login(loginData: Login): Promise { +export const login = async (loginData: Login): Promise => { return supertest(app).post("/api/v1/auth/login").send(loginData); -} +}; -export function expectLoginSuccess(response: Response): void { +export const expectLoginSuccess = (response: Response): void => { const { statusCode, headers, body } = response; expect(statusCode).toBe(STATUS_CODES.OK); @@ -27,7 +29,7 @@ export function expectLoginSuccess(response: Response): void { message: success.LOGGED_IN_SUCCESSFULLY, status: "success", }); -} +}; export const expectLoginFailed = (response: Response) => { const errorObject = errorMap[ErrorTypeEnum.enum.INVALID_CREDENTIALS]; @@ -37,16 +39,16 @@ export const expectLoginFailed = (response: Response) => { expect(response.body.code).toBe(errorObject.body.code); }; -export async function signUp(signUpData: { +export const signUp = async (signUpData: { email: string; username: string; password: string; confirmPassword: string; -}) { +}): Promise => { return await supertest(app).post("/api/v1/auth/sign-up").send(signUpData); -} +}; -export async function expectSignUpSuccess(response: Response) { +export const expectSignUpSuccess = (response: Response): void => { const { statusCode, body } = response; expect(statusCode).toBe(STATUS_CODES.CREATED); @@ -54,7 +56,7 @@ export async function expectSignUpSuccess(response: Response) { expect(body).toMatchObject({ message: success.SIGN_UP_SUCCESS, }); -} +}; export const logoutUser = async (authorizationHeader: string) => { return await supertest(app).post("/api/v1/auth/logout").set("authorization", authorizationHeader); @@ -104,26 +106,26 @@ export const verifyAccount = async (user: CreateUser) => { expectOTPVerificationSuccess(verifyResponse); }; -export async function forgetPassword(email: string): Promise { +export const forgetPassword = async (email: string): Promise => { return supertest(app).post("/api/v1/auth/forget-password").send({ email }); -} +}; -export function expectForgetPasswordSuccess(response: Response): void { +export const expectForgetPasswordSuccess = (response: Response): void => { expect(response).toBeDefined(); const { statusCode, body } = response; expect(statusCode).toBe(STATUS_CODES.OK); expect(body).toMatchObject({ message: success.FORGET_PASSWORD_EMAIL_SENT }); -} +}; -export async function resetPassword(resetPassword: ResetPassword): Promise { - return supertest(app).post(`/api/v1/auth/reset-password`).send(resetPassword); -} +export const resetPassword = async (resetPassword: ResetPassword): Promise => { + return supertest(app).post("/api/v1/auth/reset-password").send(resetPassword); +}; -export function expectResetPasswordSuccess(response: Response): void { +export const expectResetPasswordSuccess = (response: Response): void => { expect(response).toBeDefined(); const { statusCode, body } = response; expect(statusCode).toBe(STATUS_CODES.OK); expect(body).toMatchObject({ message: success.PASSWORD_RESET_SUCCESSFULLY }); -} +}; diff --git a/src/utils/test/authorize.middleware.utils.ts b/src/utils/test/authorize.middleware.utils.ts index acd3062..3d24d80 100644 --- a/src/utils/test/authorize.middleware.utils.ts +++ b/src/utils/test/authorize.middleware.utils.ts @@ -1,5 +1,6 @@ import { Response } from "supertest"; -import { errorMap, ErrorTypeEnum, STATUS_CODES } from "@/constants"; + +import { ErrorTypeEnum, STATUS_CODES, errorMap } from "@/constants"; export const expectUnauthorizedResponseForMissingAuthorizationHeader = async (response: Response) => { const errorObject = errorMap[ErrorTypeEnum.enum.NO_AUTH_HEADER]; diff --git a/src/utils/test/otp.utils.ts b/src/utils/test/otp.utils.ts index cc70a8a..503bf6e 100644 --- a/src/utils/test/otp.utils.ts +++ b/src/utils/test/otp.utils.ts @@ -1,40 +1,42 @@ import supertest, { Response } from "supertest"; -import { app } from "@/app"; -import { STATUS_CODES } from "@/constants"; + import { success } from "@/api/v1/auth/auth.constant"; import { OtpSchema, OtpType } from "@/api/v1/otp/otp.validation"; +import { app } from "@/app"; +import { STATUS_CODES } from "@/constants"; + import { OtpService } from "../../api/v1/otp/otp.service"; -export async function requestOTP(email: string): Promise { +export const requestOTP = async (email: string): Promise => { return supertest(app).post("/api/v1/otp").send({ otpType: "sendEmailVerificationOTP", email, }); -} +}; -export function expectOTPRequestSuccess(response: Response): void { +export const expectOTPRequestSuccess = (response: Response): void => { expect(response.statusCode).toBe(STATUS_CODES.OK); expect(response.body.message).toBe(success.VERIFICATION_EMAIL_SENT); -} +}; -export async function retrieveOTP(userId: string, otpType: OtpType): Promise { +export const retrieveOTP = async (userId: string, otpType: OtpType): Promise => { const otpDetails = await OtpService.getOtpDetailsByUserId({ userId, otpType, }); const otpData = otpDetails.find((data) => data.otpType === otpType); return otpData as OtpSchema; -} +}; -export async function verifyOTP({ otp, otpType }: OtpSchema, email: string): Promise { +export const verifyOTP = async ({ otp, otpType }: OtpSchema, email: string): Promise => { return supertest(app).post("/api/v1/otp/verify").send({ otpType, email, otp, }); -} +}; -export function expectOTPVerificationSuccess(response: Response): void { +export const expectOTPVerificationSuccess = (response: Response): void => { expect(response.statusCode).toBe(STATUS_CODES.OK); expect(response.body.message).toBe(success.OTP_VERIFIED); -} +}; diff --git a/src/utils/test/permission.utils.ts b/src/utils/test/permission.utils.ts index 8029be9..316b430 100644 --- a/src/utils/test/permission.utils.ts +++ b/src/utils/test/permission.utils.ts @@ -1,8 +1,9 @@ import supertest, { Response } from "supertest"; + +import { success } from "@/api/v1/permission/permission.constant"; +import { createPermission } from "@/api/v1/permission/permission.validation"; import { app } from "@/app"; import { STATUS_CODES } from "@/constants"; -import { createPermission } from "@/api/v1/permission/permission.validation"; -import { success } from "@/api/v1/permission/permission.constant"; export const createPermissionRequest = async (permission: createPermission): Promise => { return await supertest(app).post("/api/v1/permissions").send(permission); diff --git a/src/utils/test/profile.utils.ts b/src/utils/test/profile.utils.ts index 7f35f0b..83788a7 100644 --- a/src/utils/test/profile.utils.ts +++ b/src/utils/test/profile.utils.ts @@ -1,4 +1,5 @@ import supertest, { Response } from "supertest"; + import { CreateProfileData, ProfileData, success } from "@/api/v1/profile"; import { app } from "@/app"; import { STATUS_CODES } from "@/constants"; diff --git a/src/utils/test/role-permission.utils.ts b/src/utils/test/role-permission.utils.ts index bb638d8..a9dd2d3 100644 --- a/src/utils/test/role-permission.utils.ts +++ b/src/utils/test/role-permission.utils.ts @@ -1,8 +1,9 @@ import supertest, { Response } from "supertest"; -import { app } from "@/app"; + +import { success } from "@/api/v1/rolePermission/role-permission.constant"; import { RolePermission } from "@/api/v1/rolePermission/role-permission.validation"; +import { app } from "@/app"; import { STATUS_CODES } from "@/constants"; -import { success } from "@/api/v1/rolePermission/role-permission.constant"; export const createRolePermissionRequest = async (rolePermission: RolePermission, authorizationHeader: string) => { return await supertest(app) diff --git a/src/utils/test/role.utils.ts b/src/utils/test/role.utils.ts index 1e834bc..1247b0b 100644 --- a/src/utils/test/role.utils.ts +++ b/src/utils/test/role.utils.ts @@ -1,8 +1,9 @@ import supertest, { Response } from "supertest"; -import { app } from "@/app"; + +import { success } from "@/api/v1/role/role.constant"; import { createRole } from "@/api/v1/role/role.validation"; +import { app } from "@/app"; import { STATUS_CODES } from "@/constants"; -import { success } from "@/api/v1/role/role.constant"; export const createRoleRequest = async (role: createRole, authorizationHeader: string): Promise => { return supertest(app).post("/api/v1/roles").send(role).set("authorization", authorizationHeader); diff --git a/src/utils/test/user-role.utils.ts b/src/utils/test/user-role.utils.ts index dde89da..0d348e9 100644 --- a/src/utils/test/user-role.utils.ts +++ b/src/utils/test/user-role.utils.ts @@ -1,4 +1,5 @@ import supertest, { Response } from "supertest"; + import { success } from "@/api/v1/userRole/user-role.constant"; import { UserRole } from "@/api/v1/userRole/user-role.validation"; import { app } from "@/app"; diff --git a/src/utils/test/user.utils.ts b/src/utils/test/user.utils.ts index ae0036f..f7a1646 100644 --- a/src/utils/test/user.utils.ts +++ b/src/utils/test/user.utils.ts @@ -1,8 +1,10 @@ import supertest, { Response } from "supertest"; + import { app } from "@/app"; -import { errorMap, ErrorTypeEnum, STATUS_CODES } from "@/constants"; -import { CreateUser } from "../../api/v1/user/user.validation"; +import { ErrorTypeEnum, STATUS_CODES, errorMap } from "@/constants"; + import { success } from "../../api/v1/user/user.constant"; +import { CreateUser } from "../../api/v1/user/user.validation"; export const expectBadRequestResponseForValidationError = (response: Response): void => { const errorObject = errorMap[ErrorTypeEnum.enum.VALIDATION_ERROR]; @@ -15,11 +17,11 @@ export const expectBadRequestResponseForValidationError = (response: Response): }); }; -export async function createUser(user: CreateUser, authorizationHeader: string): Promise { +export const createUser = async (user: CreateUser, authorizationHeader: string): Promise => { return supertest(app).post("/api/v1/users").send(user).set("authorization", authorizationHeader); -} +}; -export function expectUserCreationSuccess(response: Response, user: CreateUser): void { +export const expectUserCreationSuccess = (response: Response, user: CreateUser): void => { expect(response).toBeDefined(); const { statusCode, body } = response; @@ -35,13 +37,13 @@ export function expectUserCreationSuccess(response: Response, user: CreateUser): expect(body.user).not.toHaveProperty("password"); expect(body.user).not.toHaveProperty("confirmPassword"); -} +}; -export async function findUserByUsername(username: string): Promise { +export const findUserByUsername = async (username: string): Promise => { return supertest(app).get(`/api/v1/users/${username}`); -} +}; -export function expectUserNotFoundError(response: Response): void { +export const expectUserNotFoundError = (response: Response): void => { const errorObject = errorMap[ErrorTypeEnum.enum.USER_NOT_FOUND]; expect(response).toBeDefined(); @@ -51,9 +53,9 @@ export function expectUserNotFoundError(response: Response): void { code: errorObject.body.code, status: "failed", }); -} +}; -export function expectFindUserByUsernameSuccess(response: Response, user: CreateUser): void { +export const expectFindUserByUsernameSuccess = (response: Response, user: CreateUser): void => { expect(response).toBeDefined(); const { statusCode, body } = response; @@ -69,13 +71,13 @@ export function expectFindUserByUsernameSuccess(response: Response, user: Create expect(body.user).not.toHaveProperty("password"); expect(body.user).not.toHaveProperty("confirmPassword"); -} +}; -export async function deleteUser(userId: string, authorizationHeader: string): Promise { +export const deleteUser = async (userId: string, authorizationHeader: string): Promise => { return supertest(app).delete(`/api/v1/users/${userId}`).set("authorization", authorizationHeader); -} +}; -export function expectDeleteUserSuccess(response: Response): void { +export const expectDeleteUserSuccess = (response: Response): void => { expect(response).toBeDefined(); const { statusCode, body } = response; @@ -88,13 +90,13 @@ export function expectDeleteUserSuccess(response: Response): void { expect(body.user).not.toHaveProperty("password"); expect(body.user).not.toHaveProperty("confirmPassword"); -} +}; -export async function restoreUser(userId: string, authorizationHeader: string): Promise { +export const restoreUser = async (userId: string, authorizationHeader: string): Promise => { return supertest(app).patch(`/api/v1/users/${userId}/restore`).set("authorization", authorizationHeader); -} +}; -export function expectRestoreUserSuccess(response: Response): void { +export const expectRestoreUserSuccess = (response: Response): void => { expect(response).toBeDefined(); const { statusCode, body } = response; @@ -107,4 +109,4 @@ export function expectRestoreUserSuccess(response: Response): void { expect(body.user).not.toHaveProperty("password"); expect(body.user).not.toHaveProperty("confirmPassword"); -} +};