diff --git a/.gitignore b/.gitignore index 64a6c9407..4cfa8f5cb 100644 --- a/.gitignore +++ b/.gitignore @@ -358,4 +358,6 @@ combine.log package-lock.json -!example.env \ No newline at end of file +!example.env + +database/ \ No newline at end of file diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 000000000..053fde7d6 --- /dev/null +++ b/nodemon.json @@ -0,0 +1,5 @@ +{ + "watch": ["src"], + "ext": "ts", + "exec": "concurrently \"npx tsc --watch\" \"ts-node src/server.ts\"" +} diff --git a/package.json b/package.json index c8deb9bdc..b2f38206c 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,14 @@ "name": "migration-v2-node-server", "version": "1.0.0", "description": "This is the TSO migration V2's node server", - "main": "index.js", + "exports": "./src/server.ts", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "npx tsc && NODE_ENV=production node dist/server.js", - "dev": "NODE_ENV=development ts-node-dev --respawn ./src/server.ts", + "build": "npx tsc", + "start": "NODE_ENV=production node dist/server.js", + "dev": "NODE_ENV=development tsx watch ./src/server.ts", "precommit": "lint-staged --concurrent false" }, - "type": "commonjs", + "type": "module", "repository": { "type": "git", "url": "git+https://github.com/contentstack-expert-services/migration-v2-node-server.git" @@ -21,7 +21,6 @@ }, "homepage": "https://github.com/contentstack-expert-services/migration-v2-node-server#readme", "dependencies": { - "@types/express": "^4.17.21", "axios": "^1.6.5", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -30,12 +29,15 @@ "express-winston": "^4.2.0", "helmet": "^7.1.0", "jsonwebtoken": "^9.0.2", + "lowdb": "^7.0.1", "mongoose": "^8.0.4", "winston": "^3.11.0" }, "devDependencies": { "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.5", + "@types/lodash": "^4.17.0", "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", @@ -44,10 +46,10 @@ "eslint-config-prettier": "^8.3.0", "husky": "^4.3.8", "lint-staged": "^15.2.2", + "lodash": "^4.17.21", "nodemon": "^3.0.2", "prettier": "^2.4.1", - "ts-node": "^10.9.2", - "ts-node-dev": "^2.0.0", + "tsx": "^4.7.1", "typescript": "^5.3.3", "validate-branch-name": "^1.3.0" }, diff --git a/src/config/index.ts b/src/config/index.ts index f1af5e87d..b6cb636eb 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,7 +1,7 @@ import dotenv from "dotenv"; import path from "path"; -import { prodConfig } from "./prod.config"; -import { devConfig } from "./dev.config"; +import { prodConfig } from "./prod.config.js"; +import { devConfig } from "./dev.config.js"; dotenv.config({ path: path.resolve(process.cwd(), `${process.env.NODE_ENV}.env`), diff --git a/src/constants/index.ts b/src/constants/index.ts index b6f9a304f..422a29407 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -37,6 +37,10 @@ export const HTTP_TEXTS = { PROJECT_CREATION_FAILED: "Error occurred while creating project.", NO_PROJECT: "resource not found with the given ID(s).", AFFIX_UPDATED: "Project's Affix updated successfully", + AFFIX_CONFIRMATION_UPDATED: + "Project's Affix confirmation updated successfully", + FILEFORMAT_CONFIRMATION_UPDATED: + "Project's Fileformat confirmation updated successfully", CMS_UPDATED: "Project's migration cms updated successfully", FILE_FORMAT_UPDATED: "Project's migration file format updated successfully", DESTINATION_STACK_UPDATED: @@ -81,6 +85,7 @@ export const VALIDATION_ERRORS = { EMAIL_LIMIT: "Email's max limit reached.", LENGTH_LIMIT: "$'s max limit reached.", STRING_REQUIRED: "Provided $ should be a string.", + BOOLEAN_REQUIRED: "Provided $ should be a boolean.", INVALID_REGION: "Provided region doesn't exists.", FIELD_REQUIRED: "Field '$' is required.", INVALID_AFFIX: "Invalid affix format", diff --git a/src/controllers/auth.controller.ts b/src/controllers/auth.controller.ts index 4537961fd..55e092e11 100644 --- a/src/controllers/auth.controller.ts +++ b/src/controllers/auth.controller.ts @@ -1,5 +1,5 @@ import { Request, Response } from "express"; -import { authService } from "../services/auth.service"; +import { authService } from "../services/auth.service.js"; const login = async (req: Request, res: Response) => { const resp = await authService.login(req); diff --git a/src/controllers/org.controller.ts b/src/controllers/org.controller.ts index 9cf5b46e6..75809a905 100644 --- a/src/controllers/org.controller.ts +++ b/src/controllers/org.controller.ts @@ -1,5 +1,5 @@ import { Request, Response } from "express"; -import { orgService } from "../services/org.service"; +import { orgService } from "../services/org.service.js"; const getAllStacks = async (req: Request, res: Response) => { const resp = await orgService.getAllStacks(req); diff --git a/src/controllers/projects.contentMapper.controller.ts b/src/controllers/projects.contentMapper.controller.ts index a706d3881..eb0c6ea29 100644 --- a/src/controllers/projects.contentMapper.controller.ts +++ b/src/controllers/projects.contentMapper.controller.ts @@ -1,5 +1,5 @@ import { Request, Response } from "express"; -import { contentMapperService } from "../services/contentMapper.service"; +import { contentMapperService } from "../services/contentMapper.service.js"; const putTestData = async (req: Request, res: Response): Promise => { const resp = await contentMapperService.putTestData(req); res.status(200).json(resp); diff --git a/src/controllers/projects.controller.ts b/src/controllers/projects.controller.ts index 01d38bded..c110d1d64 100644 --- a/src/controllers/projects.controller.ts +++ b/src/controllers/projects.controller.ts @@ -1,5 +1,5 @@ import { Request, Response } from "express"; -import { projectService } from "../services/projects.service"; +import { projectService } from "../services/projects.service.js"; const getAllProjects = async (req: Request, res: Response): Promise => { const allProjects = await projectService.getAllProjects(req); @@ -36,11 +36,21 @@ const updateAffix = async (req: Request, res: Response) => { res.status(resp.status).json(resp.data); }; +const affixConfirmation = async (req: Request, res: Response) => { + const resp = await projectService.affixConfirmation(req); + res.status(resp.status).json(resp.data); +}; + const updateFileFormat = async (req: Request, res: Response) => { const resp = await projectService.updateFileFormat(req); res.status(resp.status).json(resp.data); }; +const fileformatConfirmation = async (req: Request, res: Response) => { + const resp = await projectService.fileformatConfirmation(req); + res.status(resp.status).json(resp.data); +}; + const updateDestinationStack = async (req: Request, res: Response) => { const resp = await projectService.updateDestinationStack(req); res.status(resp.status).json(resp.data); @@ -63,7 +73,9 @@ export const projectController = { updateProject, updateLegacyCMS, updateAffix, + affixConfirmation, updateFileFormat, + fileformatConfirmation, updateDestinationStack, updateCurrentStep, deleteProject, diff --git a/src/controllers/user.controller.ts b/src/controllers/user.controller.ts index 07bfd36a9..d74936372 100644 --- a/src/controllers/user.controller.ts +++ b/src/controllers/user.controller.ts @@ -1,5 +1,5 @@ import { Request, Response } from "express"; -import { userService } from "../services/user.service"; +import { userService } from "../services/user.service.js"; const getUserProfile = async (req: Request, res: Response) => { const resp = await userService.getUserProfile(req); diff --git a/src/database.ts b/src/database.ts index 177315772..b98dd28a8 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,11 +1,12 @@ // database.ts import mongoose from "mongoose"; -import { config } from "./config"; -import logger from "./utils/logger"; -import ProjectModel from "./models/project"; -import AuthenticationModel from "./models/authentication"; -import ContentTypesMapperModel from "./models/contentTypesMapper"; -import FieldMapperModel from "./models/FieldMapper"; +import { config } from "./config/index.js"; +import logger from "./utils/logger.js"; +import ProjectModel from "./models/project.js"; +// import AuthenticationModel from "./models/authentication.js"; +import ContentTypesMapperModel from "./models/contentTypesMapper.js"; +import FieldMapperModel from "./models/FieldMapper.js"; +import fs from "fs"; const connectToDatabase = async () => { try { @@ -13,11 +14,14 @@ const connectToDatabase = async () => { ...(config.APP_ENV === "production" ? { autoIndex: false } : {}), }); - logger.info("Connected to MongoDB"); + //check if the database folder exists + if (!fs.existsSync("./database")) { + fs.mkdirSync("./database"); + } // Create the collection's if it doesn't exist await ProjectModel.init(); - await AuthenticationModel.init(); + // const AuthenticationModel = await AuthenticationDb; await ContentTypesMapperModel.init(); await FieldMapperModel.init(); } catch (error) { diff --git a/src/middlewares/auth.middleware.ts b/src/middlewares/auth.middleware.ts index 1223d204b..17987a3eb 100644 --- a/src/middlewares/auth.middleware.ts +++ b/src/middlewares/auth.middleware.ts @@ -1,8 +1,8 @@ // middleware/authentication.middleware.ts import { Request, Response, NextFunction } from "express"; import jwt from "jsonwebtoken"; -import { config } from "../config"; -import { HTTP_CODES } from "../constants"; +import { config } from "../config/index.js"; +import { HTTP_CODES } from "../constants/index.js"; export const authenticateUser = ( req: Request, diff --git a/src/middlewares/auth.migration.middleware.ts b/src/middlewares/auth.migration.middleware.ts index c6b8b482b..51216d70b 100644 --- a/src/middlewares/auth.migration.middleware.ts +++ b/src/middlewares/auth.migration.middleware.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; -import { HTTP_CODES } from "../constants"; -import { config } from "../config"; +import { HTTP_CODES } from "../constants/index.js"; +import { config } from "../config/index.js"; export const authenticateMigrationService = ( req: Request, diff --git a/src/middlewares/auth.uploadService.middleware.ts b/src/middlewares/auth.uploadService.middleware.ts index e6a5dc544..c23458493 100644 --- a/src/middlewares/auth.uploadService.middleware.ts +++ b/src/middlewares/auth.uploadService.middleware.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; -import { HTTP_CODES } from "../constants"; -import { config } from "../config"; +import { HTTP_CODES } from "../constants/index.js"; +import { config } from "../config/index.js"; export const authenticateUploadService = ( req: Request, diff --git a/src/middlewares/error.middleware.ts b/src/middlewares/error.middleware.ts index 0ad687959..199152893 100644 --- a/src/middlewares/error.middleware.ts +++ b/src/middlewares/error.middleware.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; -import { AppError } from "../utils/custom-errors.utils"; -import logger from "../utils/logger"; +import { AppError } from "../utils/custom-errors.utils.js"; +import logger from "../utils/logger.js"; export const errorMiddleware = ( err: Error, diff --git a/src/middlewares/logger.middleware.ts b/src/middlewares/logger.middleware.ts index ff260975d..0ccecbf70 100644 --- a/src/middlewares/logger.middleware.ts +++ b/src/middlewares/logger.middleware.ts @@ -1,5 +1,5 @@ import expressWinston from "express-winston"; -import logger from "../utils/logger"; +import logger from "../utils/logger.js"; //Logger Middleware to log every request const loggerMiddleware = expressWinston.logger({ diff --git a/src/middlewares/unmatched-routes.middleware.ts b/src/middlewares/unmatched-routes.middleware.ts index d7fdee816..02cd8530a 100644 --- a/src/middlewares/unmatched-routes.middleware.ts +++ b/src/middlewares/unmatched-routes.middleware.ts @@ -1,5 +1,5 @@ import { Request, Response } from "express"; -import { HTTP_CODES, HTTP_TEXTS } from "../constants"; +import { HTTP_CODES, HTTP_TEXTS } from "../constants/index.js"; export const unmatchedRoutesMiddleware = (req: Request, res: Response) => { const status = HTTP_CODES.NOT_FOUND; diff --git a/src/models/authentication.ts b/src/models/authentication.ts index b82e1088c..8672d9a70 100644 --- a/src/models/authentication.ts +++ b/src/models/authentication.ts @@ -1,26 +1,27 @@ // src/models/Authentication.ts +import { Low } from "lowdb"; +import { JSONFile } from "lowdb/node"; +import lodash from "lodash"; -import { Schema, model, Document } from "mongoose"; -import { CS_REGIONS } from "../constants"; +class LowWithLodash extends Low { + chain: lodash.ExpChain = lodash.chain(this).get("data"); +} -interface AuthenticationDocument extends Document { - user_id: string; - region: string; - authtoken: string; +interface AuthenticationDocument { + users: { + user_id: string; + region: string; + authtoken: string; + created_at: string; + updated_at: string; + }[]; } -const authenticationSchema = new Schema( - { - user_id: { type: String, required: true }, - region: { type: String, required: true, enum: CS_REGIONS }, - authtoken: { type: String, required: true }, - }, - { timestamps: { createdAt: "created_at", updatedAt: "updated_at" } } -); +const defaultData: AuthenticationDocument = { users: [] }; -const AuthenticationModel = model( - "Authentication", - authenticationSchema +const db = new LowWithLodash( + new JSONFile("database/authentication.json"), + defaultData ); -export default AuthenticationModel; +export default db; diff --git a/src/models/project.ts b/src/models/project.ts index 327dc587f..b4137dd54 100644 --- a/src/models/project.ts +++ b/src/models/project.ts @@ -5,12 +5,14 @@ import { PREDEFINED_STEPS, PROJECT_STATUS, STEPPER_STEPS, -} from "../constants"; +} from "../constants/index.js"; interface LegacyCMS { cms: string; affix: string; + affix_confirmation: boolean; file_format: string; + file_format_confirmation: boolean; file: { id: string; name: string; @@ -70,7 +72,9 @@ const projectSchema = new Schema( legacy_cms: { cms: { type: String }, affix: { type: String }, + affix_confirmation: { type: Boolean }, file_format: { type: String }, + file_format_confirmation: { type: Boolean }, file: { id: { type: String }, name: { type: String }, diff --git a/src/routes/auth.routes.ts b/src/routes/auth.routes.ts index bf162718e..29608bca9 100644 --- a/src/routes/auth.routes.ts +++ b/src/routes/auth.routes.ts @@ -1,7 +1,7 @@ import express from "express"; -import { authController } from "../controllers/auth.controller"; -import { asyncRouter } from "../utils/async-router.utils"; -import validator from "../validators"; +import { authController } from "../controllers/auth.controller.js"; +import { asyncRouter } from "../utils/async-router.utils.js"; +import validator from "../validators/index.js"; const router = express.Router(); diff --git a/src/routes/contentMapper.routes.ts b/src/routes/contentMapper.routes.ts index 2975302bf..57d90bbcf 100644 --- a/src/routes/contentMapper.routes.ts +++ b/src/routes/contentMapper.routes.ts @@ -1,6 +1,6 @@ import express from "express"; -import { contentMapperController } from "../controllers/projects.contentMapper.controller"; -import { asyncRouter } from "../utils/async-router.utils"; +import { contentMapperController } from "../controllers/projects.contentMapper.controller.js"; +import { asyncRouter } from "../utils/async-router.utils.js"; const router = express.Router({ mergeParams: true }); diff --git a/src/routes/migrationMidlleware.routes.ts b/src/routes/migrationMidlleware.routes.ts index 516a9057b..278041113 100644 --- a/src/routes/migrationMidlleware.routes.ts +++ b/src/routes/migrationMidlleware.routes.ts @@ -1,6 +1,6 @@ import express from "express"; -import { projectController } from "../controllers/projects.controller"; -import { asyncRouter } from "../utils/async-router.utils"; +import { projectController } from "../controllers/projects.controller.js"; +import { asyncRouter } from "../utils/async-router.utils.js"; const router = express.Router({ mergeParams: true }); diff --git a/src/routes/org.routes.ts b/src/routes/org.routes.ts index c06a0654d..8d8429ca7 100644 --- a/src/routes/org.routes.ts +++ b/src/routes/org.routes.ts @@ -1,7 +1,7 @@ import express from "express"; -import { orgController } from "../controllers/org.controller"; -import { asyncRouter } from "../utils/async-router.utils"; -import validator from "../validators"; +import { orgController } from "../controllers/org.controller.js"; +import { asyncRouter } from "../utils/async-router.utils.js"; +import validator from "../validators/index.js"; const router = express.Router({ mergeParams: true }); diff --git a/src/routes/projects.routes.ts b/src/routes/projects.routes.ts index d29c8b256..7450e467b 100644 --- a/src/routes/projects.routes.ts +++ b/src/routes/projects.routes.ts @@ -1,7 +1,7 @@ import express from "express"; -import { projectController } from "../controllers/projects.controller"; -import { asyncRouter } from "../utils/async-router.utils"; -import validator from "../validators"; +import { projectController } from "../controllers/projects.controller.js"; +import { asyncRouter } from "../utils/async-router.utils.js"; +import validator from "../validators/index.js"; const router = express.Router({ mergeParams: true }); @@ -31,6 +31,13 @@ router.put( asyncRouter(projectController.updateAffix) ); +// Update project's Affix confirmation +router.put( + "/:projectId/affix_confirmation", + validator("affix_confirmation_validator"), + asyncRouter(projectController.affixConfirmation) +); + // Update project's file format router.put( "/:projectId/file-format", @@ -38,6 +45,13 @@ router.put( asyncRouter(projectController.updateFileFormat) ); +// Update project's fileformat confirmation +router.put( + "/:projectId/fileformat_confirmation", + validator("fileformat_confirmation_validator"), + asyncRouter(projectController.fileformatConfirmation) +); + // Update project's destination-cms router.put( "/:projectId/destination-stack", diff --git a/src/routes/user.routes.ts b/src/routes/user.routes.ts index b69bc2d03..6e4e0bd48 100644 --- a/src/routes/user.routes.ts +++ b/src/routes/user.routes.ts @@ -1,6 +1,6 @@ import express from "express"; -import { userController } from "../controllers/user.controller"; -import { asyncRouter } from "../utils/async-router.utils"; +import { userController } from "../controllers/user.controller.js"; +import { asyncRouter } from "../utils/async-router.utils.js"; const router = express.Router(); diff --git a/src/server.ts b/src/server.ts index 03b488c03..d843c109e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,22 +1,22 @@ // file deepcode ignore UseCsurfForExpress: We've app_token for all the API calls, so we don't need CSRF token. -import { config } from "./config"; +import { config } from "./config/index.js"; import express from "express"; import cors from "cors"; import helmet from "helmet"; -import authRoutes from "./routes/auth.routes"; -import userRoutes from "./routes/user.routes"; -import projectRoutes from "./routes/projects.routes"; -import orgRoutes from "./routes/org.routes"; -import { errorMiddleware } from "./middlewares/error.middleware"; -import loggerMiddleware from "./middlewares/logger.middleware"; -import connectToDatabase from "./database"; -import { authenticateUser } from "./middlewares/auth.middleware"; -import { requestHeadersMiddleware } from "./middlewares/req-headers.middleware"; -import { unmatchedRoutesMiddleware } from "./middlewares/unmatched-routes.middleware"; -import logger from "./utils/logger"; -import contentMapperRoutes from "./routes/contentMapper.routes"; -import migrationMidllewareRoutes from "./routes/migrationMidlleware.routes"; -import { authenticateMigrationService } from "./middlewares/auth.migration.middleware"; +import authRoutes from "./routes/auth.routes.js"; +import userRoutes from "./routes/user.routes.js"; +import projectRoutes from "./routes/projects.routes.js"; +import orgRoutes from "./routes/org.routes.js"; +import { errorMiddleware } from "./middlewares/error.middleware.js"; +import loggerMiddleware from "./middlewares/logger.middleware.js"; +import connectToDatabase from "./database.js"; +import { authenticateUser } from "./middlewares/auth.middleware.js"; +import { requestHeadersMiddleware } from "./middlewares/req-headers.middleware.js"; +import { unmatchedRoutesMiddleware } from "./middlewares/unmatched-routes.middleware.js"; +import logger from "./utils/logger.js"; +import contentMapperRoutes from "./routes/contentMapper.routes.js"; +import migrationMidllewareRoutes from "./routes/migrationMidlleware.routes.js"; +import { authenticateMigrationService } from "./middlewares/auth.migration.middleware.js"; try { const app = express(); diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts index d2ca2065f..ea8fda273 100644 --- a/src/services/auth.service.ts +++ b/src/services/auth.service.ts @@ -1,17 +1,17 @@ import { Request } from "express"; -import { config } from "../config"; -import { safePromise, getLogMessage } from "../utils"; -import https from "../utils/https.utils"; -import { LoginServiceType, AppTokenPayload } from "../models/types"; -import { HTTP_CODES, HTTP_TEXTS } from "../constants"; -import { generateToken } from "../utils/jwt.utils"; +import { config } from "../config/index.js"; +import { safePromise, getLogMessage } from "../utils/index.js"; +import https from "../utils/https.utils.js"; +import { LoginServiceType, AppTokenPayload } from "../models/types.js"; +import { HTTP_CODES, HTTP_TEXTS } from "../constants/index.js"; +import { generateToken } from "../utils/jwt.utils.js"; import { BadRequestError, InternalServerError, ExceptionFunction, -} from "../utils/custom-errors.utils"; -import AuthenticationModel from "../models/authentication"; -import logger from "../utils/logger"; +} from "../utils/custom-errors.utils.js"; +import AuthenticationModel from "../models/authentication.js"; +import logger from "../utils/logger.js"; const login = async (req: Request): Promise => { const srcFun = "Login"; @@ -63,15 +63,25 @@ const login = async (req: Request): Promise => { }; // Saving auth info in the DB - await AuthenticationModel.findOneAndUpdate( - appTokenPayload, - { - authtoken: res?.data.user?.authtoken, - }, - { - upsert: true, + AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get("users") + .findIndex(appTokenPayload) + .value(); + + AuthenticationModel.update((data: any) => { + if (userIndex < 0) { + data.users.push({ + ...appTokenPayload, + authtoken: res?.data.user?.authtoken, + updated_at: new Date().toISOString(), + created_at: new Date().toISOString(), + }); + } else { + data.users[userIndex].authtoken = res?.data.user?.authtoken; + data.users[userIndex].updated_at = new Date().toISOString(); } - ); + }); // JWT token generation const app_token = generateToken(appTokenPayload); diff --git a/src/services/contentMapper.service.ts b/src/services/contentMapper.service.ts index 3a995d3cc..47a9aa58e 100644 --- a/src/services/contentMapper.service.ts +++ b/src/services/contentMapper.service.ts @@ -1,12 +1,12 @@ import { Request } from "express"; -import ContentTypesMapperModel from "../models/contentTypesMapper"; -import FieldMapperModel from "../models/FieldMapper"; -import ProjectModel from "../models/project"; -import { getLogMessage, isEmpty, safePromise } from "../utils"; +import ContentTypesMapperModel from "../models/contentTypesMapper.js"; +import FieldMapperModel from "../models/FieldMapper.js"; +import ProjectModel from "../models/project.js"; +import { getLogMessage, isEmpty, safePromise } from "../utils/index.js"; import { BadRequestError, ExceptionFunction, -} from "../utils/custom-errors.utils"; +} from "../utils/custom-errors.utils.js"; import { CONTENT_TYPE_POPULATE_FIELDS, HTTP_TEXTS, @@ -16,12 +16,12 @@ import { EXCLUDE_CONTENT_MAPPER, PROJECT_STATUS, STEPPER_STEPS, -} from "../constants"; -import logger from "../utils/logger"; -import { config } from "../config"; -import https from "../utils/https.utils"; -import getAuthtoken from "../utils/auth.utils"; -import getProjectUtil from "../utils/get-project.utils"; +} from "../constants/index.js"; +import logger from "../utils/logger.js"; +import { config } from "../config/index.js"; +import https from "../utils/https.utils.js"; +import getAuthtoken from "../utils/auth.utils.js"; +import getProjectUtil from "../utils/get-project.utils.js"; // Developer service to create dummy contentmapping data const putTestData = async (req: Request) => { diff --git a/src/services/org.service.ts b/src/services/org.service.ts index 0cc33a9c3..19f2e8e19 100644 --- a/src/services/org.service.ts +++ b/src/services/org.service.ts @@ -1,12 +1,12 @@ import { Request } from "express"; -import { config } from "../config"; -import { safePromise, getLogMessage } from "../utils/index"; -import https from "../utils/https.utils"; -import { LoginServiceType } from "../models/types"; -import getAuthtoken from "../utils/auth.utils"; -import logger from "../utils/logger"; -import { HTTP_TEXTS, HTTP_CODES } from "../constants"; -import { ExceptionFunction } from "../utils/custom-errors.utils"; +import { config } from "../config/index.js"; +import { safePromise, getLogMessage } from "../utils/index.js"; +import https from "../utils/https.utils.js"; +import { LoginServiceType } from "../models/types.js"; +import getAuthtoken from "../utils/auth.utils.js"; +import logger from "../utils/logger.js"; +import { HTTP_TEXTS, HTTP_CODES } from "../constants/index.js"; +import { ExceptionFunction } from "../utils/custom-errors.utils.js"; const getAllStacks = async (req: Request): Promise => { const srcFun = "getAllStacks"; diff --git a/src/services/projects.service.ts b/src/services/projects.service.ts index 317c76057..26f3a519d 100644 --- a/src/services/projects.service.ts +++ b/src/services/projects.service.ts @@ -1,10 +1,10 @@ import { Request } from "express"; -import ProjectModel from "../models/project"; +import ProjectModel from "../models/project.js"; import { BadRequestError, ExceptionFunction, NotFoundError, -} from "../utils/custom-errors.utils"; +} from "../utils/custom-errors.utils.js"; import { EXCLUDE_CONTENT_MAPPER, PROJECT_UNSELECTED_FIELDS, @@ -14,14 +14,14 @@ import { POPULATE_FIELD_MAPPING, PROJECT_STATUS, STEPPER_STEPS, -} from "../constants"; -import { config } from "../config"; -import { getLogMessage, isEmpty, safePromise } from "../utils"; -import getAuthtoken from "../utils/auth.utils"; -import https from "../utils/https.utils"; -import getProjectUtil from "../utils/get-project.utils"; -import logger from "../utils/logger"; -import { contentMapperService } from "./contentMapper.service"; +} from "../constants/index.js"; +import { config } from "../config/index.js"; +import { getLogMessage, isEmpty, safePromise } from "../utils/index.js"; +import getAuthtoken from "../utils/auth.utils.js"; +import https from "../utils/https.utils.js"; +import getProjectUtil from "../utils/get-project.utils.js"; +import logger from "../utils/logger.js"; +import { contentMapperService } from "./contentMapper.service.js"; const getAllProjects = async (req: Request) => { const orgId = req?.params?.orgId; @@ -306,6 +306,33 @@ const updateAffix = async (req: Request) => { }; }; +const affixConfirmation = async (req: Request) => { + const { orgId, projectId } = req.params; + const { token_payload, affix_confirmation } = req.body; + + const project = await getProjectUtil( + projectId, + { + _id: projectId, + org_id: orgId, + region: token_payload?.region, + owner: token_payload?.user_id, + }, + EXCLUDE_CONTENT_MAPPER + ); + + project.legacy_cms.affix_confirmation = affix_confirmation; + + await project.save(); + + return { + status: HTTP_CODES.OK, + data: { + message: HTTP_TEXTS.AFFIX_CONFIRMATION_UPDATED, + }, + }; +}; + const updateFileFormat = async (req: Request) => { const { orgId, projectId } = req.params; const { token_payload, file_format } = req.body; @@ -382,6 +409,33 @@ const updateFileFormat = async (req: Request) => { } }; +const fileformatConfirmation = async (req: Request) => { + const { orgId, projectId } = req.params; + const { token_payload, fileformat_confirmation } = req.body; + + const project = await getProjectUtil( + projectId, + { + _id: projectId, + org_id: orgId, + region: token_payload?.region, + owner: token_payload?.user_id, + }, + EXCLUDE_CONTENT_MAPPER + ); + + project.legacy_cms.file_format_confirmation = fileformat_confirmation; + + await project.save(); + + return { + status: HTTP_CODES.OK, + data: { + message: HTTP_TEXTS.FILEFORMAT_CONFIRMATION_UPDATED, + }, + }; +}; + const updateDestinationStack = async (req: Request) => { const { orgId, projectId } = req.params; const { token_payload, stack_api_key } = req.body; @@ -584,7 +638,9 @@ export const projectService = { updateProject, updateLegacyCMS, updateAffix, + affixConfirmation, updateFileFormat, + fileformatConfirmation, updateDestinationStack, updateCurrentStep, deleteProject, diff --git a/src/services/user.service.ts b/src/services/user.service.ts index c547890f8..5d9df450b 100644 --- a/src/services/user.service.ts +++ b/src/services/user.service.ts @@ -1,27 +1,31 @@ import { Request } from "express"; -import { config } from "../config"; -import https from "../utils/https.utils"; -import { AppTokenPayload, LoginServiceType } from "../models/types"; -import { HTTP_CODES, HTTP_TEXTS } from "../constants"; +import { config } from "../config/index.js"; +import https from "../utils/https.utils.js"; +import { AppTokenPayload, LoginServiceType } from "../models/types.js"; +import { HTTP_CODES, HTTP_TEXTS } from "../constants/index.js"; import { BadRequestError, ExceptionFunction, -} from "../utils/custom-errors.utils"; -import AuthenticationModel from "../models/authentication"; -import { safePromise, getLogMessage } from "../utils"; -import logger from "../utils/logger"; +} from "../utils/custom-errors.utils.js"; +import AuthenticationModel from "../models/authentication.js"; +import { safePromise, getLogMessage } from "../utils/index.js"; +import logger from "../utils/logger.js"; const getUserProfile = async (req: Request): Promise => { const srcFun = "getUserProfile"; const appTokenPayload: AppTokenPayload = req?.body?.token_payload; try { - const user = await AuthenticationModel.findOne({ - user_id: appTokenPayload?.user_id, - region: appTokenPayload?.region, - }).lean(); + AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get("users") + .findIndex({ + user_id: appTokenPayload?.user_id, + region: appTokenPayload?.region, + }) + .value(); - if (!user?.authtoken) throw new BadRequestError(HTTP_TEXTS.NO_CS_USER); + if (userIndex < 0) throw new BadRequestError(HTTP_TEXTS.NO_CS_USER); const [err, res] = await safePromise( https({ @@ -31,7 +35,7 @@ const getUserProfile = async (req: Request): Promise => { ]!}/user?include_orgs_roles=true`, headers: { "Content-Type": "application/json", - authtoken: user?.authtoken, + authtoken: AuthenticationModel.data.users[userIndex]?.authtoken, }, }) ); diff --git a/src/utils/auth.utils.ts b/src/utils/auth.utils.ts index 053a77593..6a5c9cebf 100644 --- a/src/utils/auth.utils.ts +++ b/src/utils/auth.utils.ts @@ -1,13 +1,19 @@ -import AuthenticationModel from "../models/authentication"; -import { UnauthorizedError } from "../utils/custom-errors.utils"; +import AuthenticationModel from "../models/authentication.js"; +import { UnauthorizedError } from "../utils/custom-errors.utils.js"; export default async (region: string, userId: string) => { - const res = await AuthenticationModel.findOne({ - region: region, - user_id: userId, - }).lean(); + AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get("users") + .findIndex({ + region: region, + user_id: userId, + }) + .value(); - if (!res?.authtoken) throw new UnauthorizedError(); + const authToken = AuthenticationModel.data.users[userIndex]?.authtoken; - return res?.authtoken; + if (userIndex < 0 || !authToken) throw new UnauthorizedError(); + + return authToken; }; diff --git a/src/utils/custom-errors.utils.ts b/src/utils/custom-errors.utils.ts index b6ff34a65..4b33d15f3 100644 --- a/src/utils/custom-errors.utils.ts +++ b/src/utils/custom-errors.utils.ts @@ -1,4 +1,4 @@ -import { HTTP_CODES, HTTP_TEXTS } from "../constants"; +import { HTTP_CODES, HTTP_TEXTS } from "../constants/index.js"; export class AppError extends Error { constructor(public statusCode: number, message: string) { diff --git a/src/utils/get-project.utils.ts b/src/utils/get-project.utils.ts index add5a064e..4a9142efd 100644 --- a/src/utils/get-project.utils.ts +++ b/src/utils/get-project.utils.ts @@ -1,12 +1,12 @@ -import ProjectModel from "../models/project"; +import ProjectModel from "../models/project.js"; import { BadRequestError, ExceptionFunction, -} from "../utils/custom-errors.utils"; -import { HTTP_CODES, HTTP_TEXTS } from "../constants"; -import { MigrationQueryType } from "../models/types"; -import { getLogMessage, isValidObjectId } from "../utils"; -import logger from "./logger"; +} from "../utils/custom-errors.utils.js"; +import { HTTP_CODES, HTTP_TEXTS } from "../constants/index.js"; +import { MigrationQueryType } from "../models/types.js"; +import { getLogMessage, isValidObjectId } from "../utils/index.js"; +import logger from "./logger.js"; export default async ( projectId: string, diff --git a/src/utils/https.utils.ts b/src/utils/https.utils.ts index c2e825add..0ab6a892e 100644 --- a/src/utils/https.utils.ts +++ b/src/utils/https.utils.ts @@ -1,5 +1,8 @@ import axios from "axios"; -import { AXIOS_TIMEOUT, METHODS_TO_INCLUDE_DATA_IN_AXIOS } from "../constants"; +import { + AXIOS_TIMEOUT, + METHODS_TO_INCLUDE_DATA_IN_AXIOS, +} from "../constants/index.js"; type httpType = { url: string; diff --git a/src/utils/jwt.utils.ts b/src/utils/jwt.utils.ts index 9d1ce88c0..d6f59aa7b 100644 --- a/src/utils/jwt.utils.ts +++ b/src/utils/jwt.utils.ts @@ -1,7 +1,7 @@ /// src/utils/jwt.utils.ts import jwt from "jsonwebtoken"; -import { AppTokenPayload } from "../models/types"; -import { config } from "../config"; +import { AppTokenPayload } from "../models/types.js"; +import { config } from "../config/index.js"; // @typescript-eslint/no-explicit-any export const generateToken = (payload: AppTokenPayload): string => { diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 36eafe798..cbde4f7b0 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -5,13 +5,9 @@ const logger = createLogger({ level: "info", format: format.combine(format.timestamp(), format.json()), transports: [ - // - Write all logs with importance level of `error` or less to `error.log` - new transports.File({ filename: "error.log", level: "error" }), // - Write all logs with importance level of `info` or less to `combined.log` new transports.File({ filename: "combine.log" }), - new transports.Console({ - format: format.combine(format.timestamp(), format.prettyPrint()), - }), + new transports.Console({}), ], }); diff --git a/src/validators/affix-confirmation.validator.ts b/src/validators/affix-confirmation.validator.ts new file mode 100644 index 000000000..5bbea21a7 --- /dev/null +++ b/src/validators/affix-confirmation.validator.ts @@ -0,0 +1,15 @@ +import { checkSchema } from "express-validator"; +import { VALIDATION_ERRORS } from "../constants/index.js"; + +export default checkSchema({ + affix_confirmation: { + in: "body", + isBoolean: { + errorMessage: VALIDATION_ERRORS.BOOLEAN_REQUIRED.replace( + "$", + "affix_confirmation" + ), + bail: true, + }, + }, +}); diff --git a/src/validators/affix.validator.ts b/src/validators/affix.validator.ts index 0174a348a..62cf4af82 100644 --- a/src/validators/affix.validator.ts +++ b/src/validators/affix.validator.ts @@ -1,5 +1,5 @@ import { checkSchema } from "express-validator"; -import { VALIDATION_ERRORS, AFFIX_REGEX } from "../constants"; +import { VALIDATION_ERRORS, AFFIX_REGEX } from "../constants/index.js"; export default checkSchema({ affix: { diff --git a/src/validators/auth.validator.ts b/src/validators/auth.validator.ts index 3446b3e8b..3ddc61d5e 100644 --- a/src/validators/auth.validator.ts +++ b/src/validators/auth.validator.ts @@ -1,5 +1,5 @@ import { checkSchema } from "express-validator"; -import { VALIDATION_ERRORS, CS_REGIONS } from "../constants"; +import { VALIDATION_ERRORS, CS_REGIONS } from "../constants/index.js"; export default checkSchema({ email: { diff --git a/src/validators/cms.validator.ts b/src/validators/cms.validator.ts index 77c339fcd..3b04f0625 100644 --- a/src/validators/cms.validator.ts +++ b/src/validators/cms.validator.ts @@ -1,5 +1,5 @@ import { checkSchema } from "express-validator"; -import { VALIDATION_ERRORS } from "../constants"; +import { VALIDATION_ERRORS } from "../constants/index.js"; export default checkSchema({ legacy_cms: { diff --git a/src/validators/destination-stack.validator.ts b/src/validators/destination-stack.validator.ts index d9cb29f06..3c48f193c 100644 --- a/src/validators/destination-stack.validator.ts +++ b/src/validators/destination-stack.validator.ts @@ -1,5 +1,5 @@ import { checkSchema } from "express-validator"; -import { VALIDATION_ERRORS } from "../constants"; +import { VALIDATION_ERRORS } from "../constants/index.js"; export default checkSchema({ stack_api_key: { diff --git a/src/validators/file-format.validator.ts b/src/validators/file-format.validator.ts index 9cf036543..22aa06b1d 100644 --- a/src/validators/file-format.validator.ts +++ b/src/validators/file-format.validator.ts @@ -1,5 +1,5 @@ import { checkSchema } from "express-validator"; -import { VALIDATION_ERRORS } from "../constants"; +import { VALIDATION_ERRORS } from "../constants/index.js"; export default checkSchema({ file_format: { diff --git a/src/validators/fileformat-confirmation.validator.ts b/src/validators/fileformat-confirmation.validator.ts new file mode 100644 index 000000000..199260966 --- /dev/null +++ b/src/validators/fileformat-confirmation.validator.ts @@ -0,0 +1,15 @@ +import { checkSchema } from "express-validator"; +import { VALIDATION_ERRORS } from "../constants/index.js"; + +export default checkSchema({ + fileformat_confirmation: { + in: "body", + isBoolean: { + errorMessage: VALIDATION_ERRORS.BOOLEAN_REQUIRED.replace( + "$", + "fileformat_confirmation" + ), + bail: true, + }, + }, +}); diff --git a/src/validators/index.ts b/src/validators/index.ts index 1418e5dd2..269e5893e 100644 --- a/src/validators/index.ts +++ b/src/validators/index.ts @@ -1,12 +1,14 @@ import { Request, NextFunction, Response } from "express"; -import { ValidationError } from "../utils/custom-errors.utils"; -import { asyncRouter } from "../utils/async-router.utils"; -import authValidator from "./auth.validator"; -import projectValidator from "./project.validator"; -import cmsValidator from "./cms.validator"; -import fileFormatValidator from "./file-format.validator"; -import destinationStackValidator from "./destination-stack.validator"; -import affixValidator from "./affix.validator"; +import { ValidationError } from "../utils/custom-errors.utils.js"; +import { asyncRouter } from "../utils/async-router.utils.js"; +import authValidator from "./auth.validator.js"; +import projectValidator from "./project.validator.js"; +import cmsValidator from "./cms.validator.js"; +import fileFormatValidator from "./file-format.validator.js"; +import destinationStackValidator from "./destination-stack.validator.js"; +import affixValidator from "./affix.validator.js"; +import affixConfirmationValidator from "./affix-confirmation.validator.js"; +import fileformatConfirmationValidator from "./fileformat-confirmation.validator.js"; export default (route: string = "") => asyncRouter(async (req: Request, res: Response, next: NextFunction) => { @@ -17,6 +19,8 @@ export default (route: string = "") => file_format: fileFormatValidator, destination_stack: destinationStackValidator, affix: affixValidator, + affix_confirmation_validator: affixConfirmationValidator, + fileformat_confirmation_validator: fileformatConfirmationValidator, }; const validator = appValidators[route as keyof typeof appValidators]; diff --git a/src/validators/project.validator.ts b/src/validators/project.validator.ts index b87f7165f..d3e97973f 100644 --- a/src/validators/project.validator.ts +++ b/src/validators/project.validator.ts @@ -1,5 +1,5 @@ import { checkSchema } from "express-validator"; -import { VALIDATION_ERRORS } from "../constants"; +import { VALIDATION_ERRORS } from "../constants/index.js"; export default checkSchema({ name: { diff --git a/tsconfig.json b/tsconfig.json index b2b4b602e..e486dfcbb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,14 @@ { "compilerOptions": { "target": "ES2022", - "module": "CommonJS", + "module": "NodeNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - "moduleResolution": "node", + "moduleResolution": "NodeNext", "allowJs": true, "baseUrl": ".", "paths": {