Skip to content

Commit

Permalink
Adding ability to delete reports by company bceid business guid
Browse files Browse the repository at this point in the history
  • Loading branch information
goemen committed May 3, 2024
1 parent 2569cfb commit 3450a18
Show file tree
Hide file tree
Showing 19 changed files with 386 additions and 144 deletions.
4 changes: 2 additions & 2 deletions backend-external/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ config.defaults({
morganFormat: 'dev',
apiKey: process.env.EXTERNAL_CONSUMER_API_KEY || 'api-key',
deleteReportsApiKey:
process.env.EXTERNAL_API_DELETE_REPORTS_KEY || 'api-key',
process.env.EXTERNAL_CONSUMER_DELETE_REPORTS_API_KEY || 'api-delete-reports-key',
port: process.env.PORT || 3002,
rateLimit: {
enabled: process.env.IS_RATE_LIMIT_ENABLED || false, // Disable if rate limiting is not required
Expand All @@ -23,7 +23,7 @@ config.defaults({
backend: {
apiKey: process.env.BACKEND_EXTERNAL_API_KEY || 'api-key',
deleteReportsApiKey:
process.env.BACKEND_EXTERNAL_DELETE_REPORTS_API_KEY || 'api-key',
process.env.BACKEND_EXTERNAL_DELETE_REPORTS_API_KEY || 'api-delete-reports-key',
url: process.env.BACKEND_URL || 'http://localhost:3010',
},
});
Expand Down
55 changes: 52 additions & 3 deletions backend-external/src/v1/routes/pay-transparency-routes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import request from 'supertest';
import router from './pay-transparency-routes';

const mockGetPayTransparencyData = jest.fn();
const mockDeleteReports = jest.fn();
jest.mock('../services/pay-transparency-service', () => ({
payTransparencyService: {
getPayTransparencyData: (...args) => mockGetPayTransparencyData(...args),
deleteReports: (...args) => mockDeleteReports(...args),
},
}));

Expand All @@ -19,13 +21,14 @@ describe('pay-transparency-routes', () => {
});

describe('/ GET', () => {
it('should return data if user doeas not send query params', () => {
it('should return data if user does not send query params', () => {
mockGetPayTransparencyData.mockReturnValue({
status: 200,
data: [{ id: 1 }],
});
return request(app)
.get('')
.set('x-api-key', 'api-key')
.expect(200)
.expect(({ body }) => {
expect(body).toHaveLength(1);
Expand All @@ -38,13 +41,59 @@ describe('pay-transparency-routes', () => {
});
return request(app)
.get('')
.query({page: 'one', pageSize: '1oooo'})
.set('x-api-key', 'api-key')
.query({ page: 'one', pageSize: '1oooo' })
.expect(400);
});
it('should fail if request fails to get reports', () => {
mockGetPayTransparencyData.mockRejectedValue({})
mockGetPayTransparencyData.mockRejectedValue({});
return request(app).get('').set('x-api-key', 'api-key').expect(500);
});

it('should return 400 if the getPayTransparencyData has error', () => {
mockGetPayTransparencyData.mockReturnValue({
data: { message: 'Failed to get reports', error: true },
});
return request(app)
.get('')
.set('x-api-key', 'api-key')
.expect(400);
});
});

describe('/delete-reports, DELETE', () => {
it('should delete reports', () => {
const message = 'Report deleted';
mockDeleteReports.mockReturnValue({
status: 200,
data: { message },
});
return request(app)
.delete('/delete-reports')
.query({ companyId: '1234567890' })
.set('x-api-delete-reports-key', 'api-delete-reports-key')
.expect(200)
.expect(({ body }) => {
expect(body).toEqual({ message });
});
});
it('should return 400 if the deleteReports has error', () => {
mockDeleteReports.mockReturnValue({
data: { message: 'Failed to delete reports', error: true },
});
return request(app)
.delete('/delete-reports')
.query({ companyId: '1234567890' })
.set('x-api-delete-reports-key', 'api-delete-reports-key')
.query({ companyId: '' })
.expect(400);
});
it('should fail if request fails to get reports', () => {
mockDeleteReports.mockRejectedValue({ message: 'Error happened' });
return request(app)
.delete('/delete-reports')
.query({ companyId: '1234567890' })
.set('x-api-delete-reports-key', 'api-delete-reports-key')
.expect(500);
});
});
Expand Down
16 changes: 12 additions & 4 deletions backend-external/src/v1/routes/pay-transparency-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { config } from '../../config';

const router = express.Router();
const validateApiKey =
(validKey: string) => (req: Request, res: Response, next: NextFunction) => {
const apiKey = req.header('x-api-key');
(validKey: string, headerKey: string = 'x-api-key') =>
(req: Request, res: Response, next: NextFunction) => {
const apiKey = req.header(headerKey);
if (apiKey) {
if (validKey === apiKey) {
next();
Expand All @@ -31,6 +32,10 @@ const validateApiKey =
* type: apiKey
* in: header
* name: x-api-key
* DeleteReportsApiKeyAuth:
* type: apiKey
* in: header
* name: x-api-delete-reports-key
* schemas:
* CalculatedData:
* type: object
Expand Down Expand Up @@ -196,7 +201,7 @@ router.get(
* summary: Delete reports
* tags: [Reports]
* security:
* - ApiKeyAuth: []
* - DeleteReportsApiKeyAuth: []
* parameters:
* - in: query
* name: companyId
Expand All @@ -216,7 +221,10 @@ router.get(
*/
router.delete(
'/delete-reports',
validateApiKey(config.get('server:deleteReportsApiKey')),
validateApiKey(
config.get('server:deleteReportsApiKey'),
'x-api-delete-reports-key',
),
async (req, res) => {
try {
const { data } = await payTransparencyService.deleteReports(req);
Expand Down
21 changes: 21 additions & 0 deletions backend-external/src/v1/services/pay-transparency-service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { payTransparencyService } from './pay-transparency-service';

const mockGet = jest.fn();
const mockDelete = jest.fn();

jest.mock('../../utils', () => ({
utils: {
backendAxios: () => ({
get: (...args) => mockGet(...args),
delete: (...args) => mockDelete(...args),
}),
},
}));
Expand Down Expand Up @@ -33,4 +35,23 @@ describe('pay-transparency-service', () => {
});
});
});

describe('deleteReports', () => {
it('should delete reports', async () => {
mockDelete.mockReturnValue({});
await payTransparencyService.deleteReports({
params: { companyId: '1234567890' },
} as any);

expect(mockDelete).toHaveBeenCalledWith(
'/external-consumer-api/v1/delete-reports',
{
params: { companyId: '1234567890' },
headers: {
'x-api-key': 'api-delete-reports-key',
},
},
);
});
});
});
34 changes: 34 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"@types/passport": "^1.0.16",
"@types/passport-jwt": "^4.0.0",
"@types/session-file-store": "^1.2.5",
"@types/supertest": "^6.0.2",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
Expand Down
2 changes: 1 addition & 1 deletion backend/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ config.defaults({
},
backendExternal: {
apiKey: process.env.BACKEND_EXTERNAL_API_KEY || 'api-key', // this the API key for internal communication between services, backend-external will pass this api key in header.
apiDeleteReportsKey: process.env.BACKEND_EXTERNAL_API_DELETE_REPORTS_KEY || 'api-key', // this the API key for internal communication between services, backend-external will pass this api key in header.
apiDeleteReportsKey: process.env.BACKEND_EXTERNAL_DELETE_REPORTS_API_KEY || 'api-delete-reports-key', // this the API key for internal communication between services, backend-external will pass this api key in header.
},
ches: {
enabled: process.env.CHES_ENABLED || false, // Enable if CHES is required, helps in local not to set up CHES
Expand Down
7 changes: 4 additions & 3 deletions backend/src/external-consumer-app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,16 @@ describe('external-consumer-app', () => {
});
it('should fail when api key is valid', async () => {
const response = await request(externalConsumerApp)
.get('/api/v1')
.get('/external-consumer-api/v1')
.set('x-api-key', 'api-key-invalid');
expect(response.status).toBe(401);
});
});
describe('without API Key', () => {
it('should fail when api key is not available', async () => {
const response = await request(externalConsumerApp)
.get('/api/v1')
const response = await request(externalConsumerApp).get(
'/external-consumer-api/v1',
);
expect(response.status).toBe(400);
});
});
Expand Down
37 changes: 36 additions & 1 deletion backend/src/v1/routes/external-consumer-routes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ jest.mock('../prisma/prisma-client-readonly-replica', () => {
};
});

const mockDeleteReports = jest.fn();
jest.mock('../services/external-consumer-service', () => ({
externalConsumerService: {
...jest.requireActual('../services/external-consumer-service')
.externalConsumerService,
deleteReports: (...args) => mockDeleteReports(...args),
},
}));

let app: Application;
const REPORT = {
report_id: faker.string.uuid(),
Expand Down Expand Up @@ -74,6 +83,7 @@ describe('external-consumer-routes', () => {
mockFindMany.mockReturnValue([REPORT]);
return request(app)
.get('')
.set('x-api-key', 'api-key')
.expect(200)
.expect(({ body }) => {
expect(body).toEqual({
Expand Down Expand Up @@ -132,6 +142,7 @@ describe('external-consumer-routes', () => {
return request(app)
.get('')
.query({ offset: 'one', limit: '1oooo' })
.set('x-api-key', 'api-key')
.expect(400)
.expect(({ body }) => {
expect(body).toEqual({
Expand All @@ -141,7 +152,31 @@ describe('external-consumer-routes', () => {
});
it('should fail if request fails to get reports', () => {
mockFindMany.mockRejectedValue({});
return request(app).get('').expect(200);
return request(app).get('').set('x-api-key', 'api-key').expect(200);
});
});

describe('/delete-reports DELETE', () => {
it('should delete reports', async () => {
const { statusCode } = await request(app)
.delete('/delete-reports')
.query({ companyId: 'companyId' })
.set('x-api-key', 'api-delete-reports-key');

expect(statusCode).toBe(200);
expect(mockDeleteReports).toHaveBeenCalledWith('companyId');
});
it('should return an error', async () => {
const errorMessage = 'Failed to delete reports';
mockDeleteReports.mockRejectedValue({ message: errorMessage });
const { statusCode, body } = await request(app)
.delete('/delete-reports')
.query({ companyId: 'companyId' })
.set('x-api-key', 'api-delete-reports-key');

expect(statusCode).toBe(200);
expect(mockDeleteReports).toHaveBeenCalledWith('companyId');
expect(body).toEqual({ error: true, message: errorMessage });
});
});
});
6 changes: 4 additions & 2 deletions backend/src/v1/routes/external-consumer-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ router.get(

router.delete(
'/delete-reports',
validateToken(config.get('backendExternal:apiDeleteReportsKey')),
async (req, res) => {

try {
await externalConsumerService.deleteReports(req.query.companyId as string);
await externalConsumerService.deleteReports(
req.query.companyId as string,
);
res.status(200).json({ error: false, message: 'Reports deleted' });
} catch (error) {
res.json({ error: true, message: error.message });
Expand Down
Loading

0 comments on commit 3450a18

Please sign in to comment.