Skip to content

Commit

Permalink
Merge pull request #614 from santoshshinde2012/dev
Browse files Browse the repository at this point in the history
fixed snyk vulnerability
  • Loading branch information
santoshshinde2012 authored May 18, 2024
2 parents a710f4e + c75dc55 commit 4951f03
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 106 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# [Node-Typescript-Boilerplate](https://blog.santoshshinde.com/skeleton-for-node-js-apps-written-in-typescript-444fa1695b30) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=santoshshinde2012_node-boilerplate&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=santoshshinde2012_node-boilerplate)![Github action workflow status](https://github.com/santoshshinde2012/node-boilerplate/actions/workflows/ci.yml/badge.svg?branch=master)![CodeQL Analysis](https://github.com/santoshshinde2012/node-boilerplate/actions/workflows/codeql-analysis.yml/badge.svg?branch=master)![njsscan Analysis](https://github.com/santoshshinde2012/node-boilerplate/actions/workflows/njsscan.yml/badge.svg?branch=master)![Maintainability](https://api.codeclimate.com/v1/badges/0e53f5d93de102b39641/maintainability)![Test Coverage](https://api.codeclimate.com/v1/badges/0e53f5d93de102b39641/test_coverage)
# [Node-Typescript-Boilerplate](https://blog.santoshshinde.com/skeleton-for-node-js-apps-written-in-typescript-444fa1695b30) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=santoshshinde2012_node-boilerplate&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=santoshshinde2012_node-boilerplate)![Github action workflow status](https://github.com/santoshshinde2012/node-boilerplate/actions/workflows/ci.yml/badge.svg?branch=master)![CodeQL Analysis](https://github.com/santoshshinde2012/node-boilerplate/actions/workflows/codeql-analysis.yml/badge.svg?branch=master)![njsscan Analysis](https://github.com/santoshshinde2012/node-boilerplate/actions/workflows/njsscan.yml/badge.svg?branch=master)![Maintainability](https://api.codeclimate.com/v1/badges/0e53f5d93de102b39641/maintainability)![Test Coverage](https://api.codeclimate.com/v1/badges/0e53f5d93de102b39641/test_coverage)![Snykk](https://snyk.io/test/github/santoshshinde2012/node-boilerplate/badge.svg?style=flat-square)

Skeleton for Node.js applications written in TypeScript

Expand Down
48 changes: 19 additions & 29 deletions src/middleware/error-handler.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,33 @@
import util from 'util';
import { Request, Response, NextFunction } from 'express';
import * as util from 'util';
import * as express from 'express';
import { StatusCodes } from 'http-status-codes';
import ApiError from '../abstractions/ApiError';
import ApiError, { IError } from '../abstractions/ApiError';
import logger from '../lib/logger';
import { getEncryptedText } from '../utils';


const addErrorHandler = (
err: ApiError | null,
req: Request,
res: Response,
next: NextFunction,
err: ApiError,
req: express.Request,
res: express.Response,
next: express.NextFunction,
): void => {
if (err) {
const status = err.status || StatusCodes.INTERNAL_SERVER_ERROR;
const errorMessage = err.message || 'An error occurred during the request.';
const errorDetails = {
const status: number = err.status || StatusCodes.INTERNAL_SERVER_ERROR;
logger.debug(`REQUEST HANDLING ERROR:
\nERROR:\n${JSON.stringify(err)}
\nREQUEST HEADERS:\n${util.inspect(req.headers)}
\nREQUEST PARAMS:\n${util.inspect(req.params)}
\nREQUEST QUERY:\n${util.inspect(req.query)}
\nBODY:\n${util.inspect(req.body)}`);
const body: IError | string = {
fields: err.fields,
message: errorMessage,
message: err.message || 'An error occurred during the request.',
name: err.name,
status,
};

// Logging error details
logger.error(`REQUEST HANDLING ERROR:
\nERROR:\n${JSON.stringify(err)}
\nREQUEST HEADERS:\n${util.inspect(req.headers)}
\nREQUEST PARAMS:\n${util.inspect(req.params)}
\nREQUEST QUERY:\n${util.inspect(req.query)}
\nBODY:\n${util.inspect(req.body)}`);

// Encrypting error details if encryption is enabled
const body = getEncryptedText(errorDetails);

res.status(status).send(body);
} else {
next();
res.status(status);
res.send(body);
}
next();
};


export default addErrorHandler;
150 changes: 74 additions & 76 deletions tests/unit-tests/middleware/error-handler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,92 +1,90 @@
import { StatusCodes } from 'http-status-codes';
import { Request, Response, NextFunction } from 'express';
import 'jest';
import { NextFunction, Request, Response } from 'express';
import addErrorHandler from '../../../src/middleware/error-handler';
import logger from '../../../src/lib/logger';
import { getEncryptedText } from '../../../src/utils';
import ApiError from '../../../src/abstractions/ApiError';

jest.mock('../../../src/lib/logger', () => ({
error: jest.fn(),
}));

jest.mock('../../../src/utils', () => ({
getEncryptedText: jest.fn((errorDetails) => JSON.stringify(errorDetails)),
}));
import { StatusCodes } from 'http-status-codes';

describe('addErrorHandler', () => {
let req: Partial<Request>;
let res: Partial<Response>;
let next: jest.Mock<NextFunction, []>;
describe('ErrorHandler middleware', () => {
let mockRequest: Partial<Request>;
let mockResponse: Partial<Response>;
let nextFunction: NextFunction = jest.fn();

beforeEach(() => {
req = {
headers: {},
params: {},
query: {},
body: {},
};
res = {
status: jest.fn().mockReturnThis(),
send: jest.fn(),
mockRequest = {};
mockResponse = {
status : jest.fn(),
send: jest.fn()
};
next = jest.fn();
});

afterEach(() => {
jest.clearAllMocks();
});
test('with 0 status code', async () => {
const status: number = StatusCodes.INTERNAL_SERVER_ERROR;
addErrorHandler({
status: 0,
success: false,
fields: {
name: {
message: ''
}
},
name: '',
message: ''
}, mockRequest as Request, mockResponse as Response, nextFunction);

it('should send encrypted error response', () => {
const err = new Error('Test Error') as ApiError;
err.status = StatusCodes.BAD_REQUEST;
expect(mockResponse.status).toHaveBeenCalledWith(status);
});

addErrorHandler(err, req as Request, res as Response, next);
test('with 200 status code', async () => {
const status: number = 200;
addErrorHandler({
status,
success: false,
fields: {
name: {
message: ''
}
},
name: '',
message: ''
}, mockRequest as Request, mockResponse as Response, nextFunction);

expect(logger.error).toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(StatusCodes.BAD_REQUEST);
expect(getEncryptedText).toHaveBeenCalledWith({
fields: undefined,
message: 'Test Error',
name: 'Error',
status: StatusCodes.BAD_REQUEST,
});
expect(res.send).toHaveBeenCalledWith(JSON.stringify({
fields: undefined,
message: 'Test Error',
name: 'Error',
status: StatusCodes.BAD_REQUEST,
}));
expect(next).not.toHaveBeenCalled();
expect(mockResponse.status).toHaveBeenCalledWith(status);
});

it('should call next if no error', () => {
addErrorHandler(null, req as Request, res as Response, next);

expect(logger.error).not.toHaveBeenCalled();
expect(res.status).not.toHaveBeenCalled();
expect(res.send).not.toHaveBeenCalled();
expect(next).toHaveBeenCalled();
});

test('with 200 status code', async () => {
const status: number = 200;
addErrorHandler({
status,
success: false,
fields: {
name: {
message: ''
}
},
name: '',
message: ''
}, mockRequest as Request, mockResponse as Response, nextFunction);

it('should handle error without status', () => {
const err = new Error('Test Error') as ApiError;
expect(mockResponse.status).toHaveBeenCalledWith(status);
});

addErrorHandler(err, req as Request, res as Response, next);
test('with 200 status code and updated env variables', async () => {
process.env.APPLY_ENCRYPTION = 'true';
process.env.SECRET_KEY = 'key';
const status: number = 200;
addErrorHandler({
status,
success: false,
fields: {
name: {
message: ''
}
},
name: '',
message: ''
}, mockRequest as Request, mockResponse as Response, nextFunction);

expect(logger.error).toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(StatusCodes.INTERNAL_SERVER_ERROR);
expect(getEncryptedText).toHaveBeenCalledWith({
fields: undefined,
message: 'Test Error',
name: 'Error',
status: StatusCodes.INTERNAL_SERVER_ERROR,
});
expect(res.send).toHaveBeenCalledWith(JSON.stringify({
fields: undefined,
message: 'Test Error',
name: 'Error',
status: StatusCodes.INTERNAL_SERVER_ERROR,
}));
expect(next).not.toHaveBeenCalled();
expect(mockResponse.status).toHaveBeenCalledWith(status);
});
});

})

0 comments on commit 4951f03

Please sign in to comment.