From 2231240e6071bab5209633aec223d00dc3147fec Mon Sep 17 00:00:00 2001 From: tap0212 Date: Sun, 25 Oct 2020 23:36:35 +0530 Subject: [PATCH 1/6] added lambdas and tests --- aws/apigateway-aurora-lambda/README.md | 27 +++--- .../__mocks__/constants.js | 15 +++- .../functions/employee-office/join/data.json | 7 ++ .../functions/employee-office/join/index.js | 28 +++++++ .../employee-office/join/package.json | 12 +++ .../employee-office/join/tests/index.test.js | 44 ++++++++++ .../functions/employee/get-employee/data.json | 7 ++ .../functions/employee/get-employee/index.js | 19 +++++ .../employee/get-employee/package.json | 12 +++ .../employee/get-employee/tests/index.test.js | 38 +++++++++ .../employee/get-employees/data.json | 7 ++ .../functions/employee/get-employees/index.js | 25 ++++++ .../employee/get-employees/package.json | 12 +++ .../get-employees/tests/index.test.js | 54 ++++++++++++ .../functions/employee/put-employee/data.json | 7 ++ .../functions/employee/put-employee/index.js | 20 +++++ .../employee/put-employee/package.json | 12 +++ .../employee/put-employee/tests/index.test.js | 37 +++++++++ .../functions/office/get-office/data.json | 7 ++ .../functions/office/get-office/index.js | 20 +++++ .../functions/office/get-office/package.json | 12 +++ .../office/get-office/tests/index.test.js | 38 +++++++++ .../functions/office/get-offices/data.json | 7 ++ .../functions/office/get-offices/index.js | 26 ++++++ .../functions/office/get-offices/package.json | 12 +++ .../office/get-offices/tests/index.test.js | 54 ++++++++++++ .../functions/office/put-office/data.json | 7 ++ .../functions/office/put-office/index.js | 24 ++++++ .../functions/office/put-office/package.json | 12 +++ .../office/put-office/tests/index.test.js | 37 +++++++++ .../functions/uuid/put/data.json | 7 ++ .../functions/uuid/put/index.js | 37 ++++++--- .../functions/uuid/put/tests/index.test.js | 35 ++++++-- .../migrations/resources/v1/02_employees.sql | 6 ++ .../migrations/resources/v1/03_office.sql | 8 ++ .../resources/v1/04_employee_office.sql | 11 +++ .../resources/v1/alter_employees.sql | 1 + .../models/employee_office.js | 56 +++++++++++++ .../models/employees.js | 36 ++++++++ aws/apigateway-aurora-lambda/models/index.js | 7 ++ .../models/offices.js | 40 +++++++++ aws/apigateway-aurora-lambda/models/uuids.js | 45 +++++----- aws/apigateway-aurora-lambda/serverless.yml | 65 ++++++++++++--- aws/apigateway-aurora-lambda/setup-lambda.sh | 9 ++ aws/apigateway-aurora-lambda/utils/index.js | 23 ++++++ .../utils/testUtils.js | 35 +++++++- .../utils/tests/indes.test.js | 82 +++++++++++++++++++ 47 files changed, 1075 insertions(+), 67 deletions(-) create mode 100644 aws/apigateway-aurora-lambda/functions/employee-office/join/data.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee-office/join/index.js create mode 100644 aws/apigateway-aurora-lambda/functions/employee-office/join/package.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employee/data.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employee/index.js create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employee/package.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employee/tests/index.test.js create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employees/data.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employees/package.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js create mode 100644 aws/apigateway-aurora-lambda/functions/employee/put-employee/data.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee/put-employee/index.js create mode 100644 aws/apigateway-aurora-lambda/functions/employee/put-employee/package.json create mode 100644 aws/apigateway-aurora-lambda/functions/employee/put-employee/tests/index.test.js create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-office/data.json create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-office/index.js create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-office/package.json create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-office/tests/index.test.js create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-offices/data.json create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-offices/index.js create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-offices/package.json create mode 100644 aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js create mode 100644 aws/apigateway-aurora-lambda/functions/office/put-office/data.json create mode 100644 aws/apigateway-aurora-lambda/functions/office/put-office/index.js create mode 100644 aws/apigateway-aurora-lambda/functions/office/put-office/package.json create mode 100644 aws/apigateway-aurora-lambda/functions/office/put-office/tests/index.test.js create mode 100644 aws/apigateway-aurora-lambda/functions/uuid/put/data.json create mode 100644 aws/apigateway-aurora-lambda/migrations/resources/v1/02_employees.sql create mode 100644 aws/apigateway-aurora-lambda/migrations/resources/v1/03_office.sql create mode 100644 aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql create mode 100644 aws/apigateway-aurora-lambda/migrations/resources/v1/alter_employees.sql create mode 100644 aws/apigateway-aurora-lambda/models/employee_office.js create mode 100644 aws/apigateway-aurora-lambda/models/employees.js create mode 100644 aws/apigateway-aurora-lambda/models/offices.js create mode 100755 aws/apigateway-aurora-lambda/setup-lambda.sh create mode 100644 aws/apigateway-aurora-lambda/utils/index.js create mode 100644 aws/apigateway-aurora-lambda/utils/tests/indes.test.js diff --git a/aws/apigateway-aurora-lambda/README.md b/aws/apigateway-aurora-lambda/README.md index afc4cc1..7ec279c 100644 --- a/aws/apigateway-aurora-lambda/README.md +++ b/aws/apigateway-aurora-lambda/README.md @@ -3,14 +3,13 @@

-

UUID

+

Offices and Employees

- Write a backend that exposes an endpoint that whenever invoked generates a new UUID, writes that to the database and returns it to the calling client. The backend should also expose an API that accepts a UUID and updates the updated_at timestamp if its already present in the db, else inserts it. + Write a multi-tenant backend for a SAAS ERP solution which allows storage/retrieval/manipulation of offices and employee data. Employees can work in multiple offices and each office can have multiple employees.

- ___ - +---

@@ -27,19 +26,27 @@

- ___ +--- + +We’re always looking for people who value their work, so come and join us. We are hiring! - We’re always looking for people who value their work, so come and join us. We are hiring! ## Rest APIs + Use API Gateway to expose a backend that provides -- a GET request that returns a new UUID when invoked and writes the value to a mysql variant of Aurora DB -- a PUT request that accepts a UUID, updates the updated_at timestamp if its already present in the db, else inserts it. + +- a PUT request that writes the employee details to a mysql variant of Aurora DB +- a PUT request that writes the office details to a mysql variant of Aurora DB +- a GET request that queries the DB by employeeId and returns the employee info +- a GET request that queries the DB by officeId and returns the office info +- a PUT request that associates office with employee +- a GET request that queries the DB and returns the all the offices or all the offices of a particular employee with pagination support +- a GET request that queries the DB and returns the all the employees or all the employees of a particular office with pagination support ## Migrations -Migrations are handled using sequelize. After a successful deployment a migration script is triggered by executing the following command: +Migrations are handled using sequelize. After a successful deployment a migration script is triggered by executing the following command: `sls migrations up --host= --stage=` -The host URL is fetched by querying the cloudformation Output for the RDSHost. +The host URL is fetched by querying the cloudformation Output for the RDSHost. diff --git a/aws/apigateway-aurora-lambda/__mocks__/constants.js b/aws/apigateway-aurora-lambda/__mocks__/constants.js index 580af64..2652468 100644 --- a/aws/apigateway-aurora-lambda/__mocks__/constants.js +++ b/aws/apigateway-aurora-lambda/__mocks__/constants.js @@ -5,5 +5,18 @@ MockDate.set('2000-11-22'); export const CONSTANTS = { uuid: 'uuid', - updatedAt: moment().format('YYYY-MM-DD HH:mm:s:ss') + updatedAt: moment().format('YYYY-MM-DD HH:mm:s:ss'), + employee: { + id: 1, + employee_name: 'Tapan', + office_id: null, + updated_at: '2020-10-25T16:02:21.000Z' + }, + office: { + id: 1, + office_name: 'Wednesday Solutions', + office_address: 'Pune, MH, India', + employee_id: null, + updated_at: '2020-10-25T16:01:55.000Z' + } }; diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/data.json b/aws/apigateway-aurora-lambda/functions/employee-office/join/data.json new file mode 100644 index 0000000..4b3a077 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"employeeId\":1, \"officeId\":2}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js b/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js new file mode 100644 index 0000000..bc10f6e --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js @@ -0,0 +1,28 @@ +import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + const { employeeId, officeId } = JSON.parse(event.body); + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + console.log({ employeeId, officeId }); + const employee = await getDB().employees.findOne({ where: { id: employeeId }, raw: true }); + const office = await getDB().offices.findOne({ where: { id: officeId }, raw: true }); + const res = await getDB().employee_office.upsert({ + office_id: office.id, + employee_id: employee.id, + employee_name: employee.employee_name, + office_name: office.office_name, + office_address: office.office_address + }); + return success(callback, { + status: 200, + body: JSON.stringify({ res }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/package.json b/aws/apigateway-aurora-lambda/functions/employee-office/join/package.json new file mode 100644 index 0000000..ab8c871 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/package.json @@ -0,0 +1,12 @@ +{ + "name": "join", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js new file mode 100644 index 0000000..fbf56df --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js @@ -0,0 +1,44 @@ +import { resetAndMockDB } from '@utils/testUtils'; +import { CONSTANTS } from '@mocks/constants'; + +describe('join-office-employee', () => { + let event; + let mocks; + + beforeEach(() => { + event = require('../data.json'); + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should update/put an employee', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.employees.findOne = () => CONSTANTS.employee; + }); + await resetAndMockDB(mockDbs => { + mockDbs.offices.findOne = () => CONSTANTS.office; + }); + await resetAndMockDB(mockDbs => { + mockDbs.employee_office.upsert = () => true; + }); + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: true }) + }); + }); + + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); +}); diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employee/data.json b/aws/apigateway-aurora-lambda/functions/employee/get-employee/data.json new file mode 100644 index 0000000..7453f56 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employee/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"employeeId\":\"1\"}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employee/index.js b/aws/apigateway-aurora-lambda/functions/employee/get-employee/index.js new file mode 100644 index 0000000..74a1e9c --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employee/index.js @@ -0,0 +1,19 @@ +import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + const { employeeId } = JSON.parse(event.body); + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + const res = await getDB().employees.findOne({ where: { id: employeeId }, raw: true }); + return success(callback, { + status: 200, + body: JSON.stringify({ res }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employee/package.json b/aws/apigateway-aurora-lambda/functions/employee/get-employee/package.json new file mode 100644 index 0000000..10ccf62 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employee/package.json @@ -0,0 +1,12 @@ +{ + "name": "getEmployee", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employee/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee/get-employee/tests/index.test.js new file mode 100644 index 0000000..f87b585 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employee/tests/index.test.js @@ -0,0 +1,38 @@ +import { CONSTANTS } from '@mocks/constants'; +import { resetAndMockDB } from '@utils/testUtils'; + +describe('get-employee', () => { + let event; + let mocks; + + beforeEach(() => { + event = require('../data.json'); + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should fetch employee with employeeId', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.employees.findOne = () => CONSTANTS.employee; + }); + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: CONSTANTS.employee }) + }); + }); + + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); +}); diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/data.json b/aws/apigateway-aurora-lambda/functions/employee/get-employees/data.json new file mode 100644 index 0000000..c7c0ac4 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"officeId\":1}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js new file mode 100644 index 0000000..e523568 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js @@ -0,0 +1,25 @@ +import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + const { limit, offset, officeId } = JSON.parse(event.body); + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + let res; + if (!officeId) { + res = await getDB().employees.findAll(); + } else { + res = await getDB().employee_office.findAll({ limit, offset, where: { office_id: officeId } }); + } + console.log(res); + return success(callback, { + status: 200, + body: JSON.stringify({ res }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/package.json b/aws/apigateway-aurora-lambda/functions/employee/get-employees/package.json new file mode 100644 index 0000000..ed014a2 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/package.json @@ -0,0 +1,12 @@ +{ + "name": "get-employees", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js new file mode 100644 index 0000000..093de3f --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js @@ -0,0 +1,54 @@ +import { CONSTANTS } from '@mocks/constants'; +import { resetAndMockDB } from '@utils/testUtils'; + +describe('get-employees', () => { + let event; + let mocks; + + beforeEach(() => { + event = require('../data.json'); + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should fetch all employees', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.employees.findAll = () => [CONSTANTS.employee]; + }); + const handler = require('../index').handler; + event.body = '{}'; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: [CONSTANTS.employee] }) + }); + }); + + it('should fetch all employees of the given officeId', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.employee_office.findAll = () => [CONSTANTS.employee]; + }); + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: [CONSTANTS.employee] }) + }); + }); + + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); +}); diff --git a/aws/apigateway-aurora-lambda/functions/employee/put-employee/data.json b/aws/apigateway-aurora-lambda/functions/employee/put-employee/data.json new file mode 100644 index 0000000..677b2b4 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/put-employee/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"employeeName\":\"Mac\"}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/employee/put-employee/index.js b/aws/apigateway-aurora-lambda/functions/employee/put-employee/index.js new file mode 100644 index 0000000..bd1d185 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/put-employee/index.js @@ -0,0 +1,20 @@ +import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + const { employeeName, officeId } = JSON.parse(event.body); + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + const res = await getDB().employees.upsert({ employee_name: employeeName, office_id: officeId }); + + return success(callback, { + status: 200, + body: JSON.stringify({ res }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/employee/put-employee/package.json b/aws/apigateway-aurora-lambda/functions/employee/put-employee/package.json new file mode 100644 index 0000000..728ba78 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/put-employee/package.json @@ -0,0 +1,12 @@ +{ + "name": "putEmployee", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/aws/apigateway-aurora-lambda/functions/employee/put-employee/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee/put-employee/tests/index.test.js new file mode 100644 index 0000000..0c5d0f4 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/employee/put-employee/tests/index.test.js @@ -0,0 +1,37 @@ +import { resetAndMockDB } from '@utils/testUtils'; + +describe('put-employee', () => { + let event; + let mocks; + + beforeEach(() => { + event = require('../data.json'); + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should update/put an employee', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.employees.upsert = () => true; + }); + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: true }) + }); + }); + + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); +}); diff --git a/aws/apigateway-aurora-lambda/functions/office/get-office/data.json b/aws/apigateway-aurora-lambda/functions/office/get-office/data.json new file mode 100644 index 0000000..6ae18df --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-office/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"officeId\":\"1\"}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/office/get-office/index.js b/aws/apigateway-aurora-lambda/functions/office/get-office/index.js new file mode 100644 index 0000000..2186d62 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-office/index.js @@ -0,0 +1,20 @@ +import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + const { officeId } = JSON.parse(event.body); + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + const res = await getDB().offices.findOne({ where: { id: officeId }, raw: true }); + console.log({ res }); + return success(callback, { + status: 200, + body: JSON.stringify({ res }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/office/get-office/package.json b/aws/apigateway-aurora-lambda/functions/office/get-office/package.json new file mode 100644 index 0000000..5f81265 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-office/package.json @@ -0,0 +1,12 @@ +{ + "name": "get-office", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/aws/apigateway-aurora-lambda/functions/office/get-office/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/office/get-office/tests/index.test.js new file mode 100644 index 0000000..c0f60f8 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-office/tests/index.test.js @@ -0,0 +1,38 @@ +import { CONSTANTS } from '@mocks/constants'; +import { resetAndMockDB } from '@utils/testUtils'; + +describe('get-office', () => { + let event; + let mocks; + + beforeEach(() => { + event = require('../data.json'); + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should fetch office with officeId', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.offices.findOne = () => CONSTANTS.office; + }); + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: CONSTANTS.office }) + }); + }); + + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); +}); diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/data.json b/aws/apigateway-aurora-lambda/functions/office/get-offices/data.json new file mode 100644 index 0000000..e1ac41b --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"employeeId\":1}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js new file mode 100644 index 0000000..7fb432c --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js @@ -0,0 +1,26 @@ +import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + const { limit, offset, employeeId } = JSON.parse(event.body); + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + let res; + console.log({ limit, offset }); + if (!employeeId) { + res = await getDB().offices.findAll(); + } else { + res = await getDB().employee_office.findAll({ limit, offset, where: { employee_id: employeeId } }); + } + + return success(callback, { + status: 200, + body: JSON.stringify({ res }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/package.json b/aws/apigateway-aurora-lambda/functions/office/get-offices/package.json new file mode 100644 index 0000000..ab69a02 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/package.json @@ -0,0 +1,12 @@ +{ + "name": "get-offices", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js new file mode 100644 index 0000000..ef0aefd --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js @@ -0,0 +1,54 @@ +import { CONSTANTS } from '@mocks/constants'; +import { resetAndMockDB } from '@utils/testUtils'; + +describe('get-offices', () => { + let event; + let mocks; + + beforeEach(() => { + event = require('../data.json'); + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should fetch all offices', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.offices.findAll = () => [CONSTANTS.office]; + }); + const handler = require('../index').handler; + event.body = '{}'; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: [CONSTANTS.office] }) + }); + }); + + it('should fetch all offices of the given employeeId', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.employee_office.findAll = () => [CONSTANTS.office]; + }); + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: [CONSTANTS.office] }) + }); + }); + + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); +}); diff --git a/aws/apigateway-aurora-lambda/functions/office/put-office/data.json b/aws/apigateway-aurora-lambda/functions/office/put-office/data.json new file mode 100644 index 0000000..3bd68ab --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/put-office/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"officeName\":\"WS\", \"officeAddress\":\"Pune, MH, India\"}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/office/put-office/index.js b/aws/apigateway-aurora-lambda/functions/office/put-office/index.js new file mode 100644 index 0000000..70f3092 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/put-office/index.js @@ -0,0 +1,24 @@ +import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + const { officeName, officeAddress, employeeId } = JSON.parse(event.body); + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + const res = await getDB().offices.upsert({ + office_name: officeName, + office_address: officeAddress, + employee_id: employeeId + }); + + return success(callback, { + status: 200, + body: JSON.stringify({ res }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/office/put-office/package.json b/aws/apigateway-aurora-lambda/functions/office/put-office/package.json new file mode 100644 index 0000000..728ba78 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/put-office/package.json @@ -0,0 +1,12 @@ +{ + "name": "putEmployee", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/aws/apigateway-aurora-lambda/functions/office/put-office/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/office/put-office/tests/index.test.js new file mode 100644 index 0000000..4f42413 --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/office/put-office/tests/index.test.js @@ -0,0 +1,37 @@ +import { resetAndMockDB } from '@utils/testUtils'; + +describe('put-office', () => { + let event; + let mocks; + + beforeEach(() => { + event = require('../data.json'); + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should update/put an office', async () => { + await resetAndMockDB(mockDbs => { + mockDbs.offices.upsert = () => true; + }); + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + expect(mocks.callback.mock.calls[0][1]).toEqual({ + status: 200, + body: JSON.stringify({ res: true }) + }); + }); + + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); +}); diff --git a/aws/apigateway-aurora-lambda/functions/uuid/put/data.json b/aws/apigateway-aurora-lambda/functions/uuid/put/data.json new file mode 100644 index 0000000..ebcec2c --- /dev/null +++ b/aws/apigateway-aurora-lambda/functions/uuid/put/data.json @@ -0,0 +1,7 @@ +{ + "body": "{\"uuid\":\"bf1cb7b6-6199-488a-a485-8b72e74c8c95\"}", + "headers": { + "content-type": "application/json", + "x-ws-system-id": "WS" + } +} diff --git a/aws/apigateway-aurora-lambda/functions/uuid/put/index.js b/aws/apigateway-aurora-lambda/functions/uuid/put/index.js index a553b52..58e31e9 100644 --- a/aws/apigateway-aurora-lambda/functions/uuid/put/index.js +++ b/aws/apigateway-aurora-lambda/functions/uuid/put/index.js @@ -1,15 +1,28 @@ import moment from 'moment'; import { getDB } from '@models'; +import { success, failure, logHandler, getSystemId } from '@utils'; -export const handler = async event => { - const { uuid } = JSON.parse(event.body); - const dbResponse = await getDB().uuids.findOne({ where: { uuid }, raw: true }); - let newUUID; - if (dbResponse) { - await getDB().uuids.update({ updatedAt: moment() }, { where: { id: dbResponse.id } }); - newUUID = await getDB().uuids.findOne({ where: { uuid }, raw: true }); - } else { - newUUID = await getDB().uuids.create({ uuid }); - } - return { status: 200, body: JSON.stringify({ uuid: newUUID.uuid, updated_at: newUUID.updatedAt }) }; -}; +export const handler = async (event, context, callback) => + logHandler(event, async () => { + try { + if (!getSystemId(event)) { + throw new Error('Request Id Missing!'); + } + const { uuid } = JSON.parse(event.body); + const dbResponse = await getDB().uuids.findOne({ where: { uuid }, raw: true }); + let newUUID; + if (dbResponse) { + await getDB().uuids.update({ updatedAt: moment() }, { where: { id: dbResponse.id } }); + newUUID = await getDB().uuids.findOne({ where: { uuid }, raw: true }); + } else { + newUUID = await getDB().uuids.create({ uuid }); + } + return success(callback, { + status: 200, + body: JSON.stringify({ uuid: newUUID.uuid, updated_at: newUUID.updatedAt }) + }); + } catch (err) { + console.log(err); + return failure(callback, err); + } + }); diff --git a/aws/apigateway-aurora-lambda/functions/uuid/put/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/uuid/put/tests/index.test.js index 4a70e94..60bc634 100644 --- a/aws/apigateway-aurora-lambda/functions/uuid/put/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/uuid/put/tests/index.test.js @@ -2,13 +2,24 @@ import { CONSTANTS } from '@mocks/constants'; import { resetAndMockDB } from '@utils/testUtils'; describe('put-uuid', () => { + let mocks; + let event; + + beforeEach(() => { + event = require('../data.json'); + + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); it('should update the updatedAt if the UUID is already present', async () => { resetAndMockDB(); const handler = require('../index').handler; - const response = await handler({ body: `{"uuid": "${CONSTANTS.uuid}"}` }); - const body = JSON.parse(response.body); - expect(body.uuid).toEqual(CONSTANTS.uuid); - expect(body.updated_at).toEqual('2000-11-22T00:00:00.000Z'); + await handler({ body: `{"uuid": "${CONSTANTS.uuid}"}`, headers: event.headers }, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); }); it('should add a new UUID', async () => { @@ -18,9 +29,17 @@ describe('put-uuid', () => { mockDbs.uuids.create = () => ({ uuid: newUUID, updatedAt: CONSTANTS.updatedAt }); }); const handler = require('../index').handler; - const response = await handler({ body: `{"uuid": "${CONSTANTS.uuid}"}` }); - const body = JSON.parse(response.body); - expect(body.uuid).toEqual(newUUID); - expect(body.updated_at).toEqual(CONSTANTS.updatedAt); + await handler({ body: `{"uuid": "${CONSTANTS.uuid}"}`, headers: event.headers }, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); + }); + it('should throw an error when req Id is missing', async () => { + event.headers['x-ws-system-id'] = null; + const handler = require('../index').handler; + await handler(event, null, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + expect(mocks.callback.mock.calls[0][0]).toStrictEqual(`Request Id Missing!`); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); }); }); diff --git a/aws/apigateway-aurora-lambda/migrations/resources/v1/02_employees.sql b/aws/apigateway-aurora-lambda/migrations/resources/v1/02_employees.sql new file mode 100644 index 0000000..8bd1ce1 --- /dev/null +++ b/aws/apigateway-aurora-lambda/migrations/resources/v1/02_employees.sql @@ -0,0 +1,6 @@ +create table employees ( + id INT PRIMARY KEY AUTO_INCREMENT, + employee_name VARCHAR(36) UNIQUE NOT NULL, + office_id INT, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/aws/apigateway-aurora-lambda/migrations/resources/v1/03_office.sql b/aws/apigateway-aurora-lambda/migrations/resources/v1/03_office.sql new file mode 100644 index 0000000..c7b0c65 --- /dev/null +++ b/aws/apigateway-aurora-lambda/migrations/resources/v1/03_office.sql @@ -0,0 +1,8 @@ +create table offices ( + id INT PRIMARY KEY AUTO_INCREMENT, + office_name VARCHAR(36) UNIQUE NOT NULL, + office_address VARCHAR(36) NOT NULL, + employee_id INT, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT offices_employee_id_fk FOREIGN KEY (employee_id) REFERENCES employees (id) +); \ No newline at end of file diff --git a/aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql b/aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql new file mode 100644 index 0000000..8986481 --- /dev/null +++ b/aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql @@ -0,0 +1,11 @@ +create table employee_office ( + id INT PRIMARY KEY AUTO_INCREMENT, + office_name VARCHAR(36) NOT NULL, + office_address VARCHAR(36) NOT NULL, + employee_name VARCHAR(36) NOT NULL, + employee_id INT NOT NULL, + office_id INT NOT NULL, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT employee_id_fk FOREIGN KEY (employee_id) REFERENCES employees (id), + CONSTRAINT office_id_fk FOREIGN KEY (office_id) REFERENCES offices (id) +); \ No newline at end of file diff --git a/aws/apigateway-aurora-lambda/migrations/resources/v1/alter_employees.sql b/aws/apigateway-aurora-lambda/migrations/resources/v1/alter_employees.sql new file mode 100644 index 0000000..7b854df --- /dev/null +++ b/aws/apigateway-aurora-lambda/migrations/resources/v1/alter_employees.sql @@ -0,0 +1 @@ +alter table employees add foreign key (office_id) references offices(id); diff --git a/aws/apigateway-aurora-lambda/models/employee_office.js b/aws/apigateway-aurora-lambda/models/employee_office.js new file mode 100644 index 0000000..e6fa73c --- /dev/null +++ b/aws/apigateway-aurora-lambda/models/employee_office.js @@ -0,0 +1,56 @@ +/* jshint indent: 2 */ + +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define( + 'employee_office', + { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + office_name: { + type: DataTypes.STRING(36), + allowNull: false + }, + office_address: { + type: DataTypes.STRING(36), + allowNull: false + }, + employee_name: { + type: DataTypes.STRING(36), + allowNull: false + }, + employee_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'employees', + key: 'id' + }, + unique: 'employee_id_fk' + }, + office_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'offices', + key: 'id' + }, + unique: 'office_id_fk' + }, + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, + { + sequelize, + tableName: 'employee_office', + timestamps: false + } + ); +}; diff --git a/aws/apigateway-aurora-lambda/models/employees.js b/aws/apigateway-aurora-lambda/models/employees.js new file mode 100644 index 0000000..17c18cf --- /dev/null +++ b/aws/apigateway-aurora-lambda/models/employees.js @@ -0,0 +1,36 @@ +/* jshint indent: 2 */ + +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('employees', { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + employee_name: { + type: DataTypes.STRING(36), + allowNull: false, + unique: "employee_name" + }, + office_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'offices', + key: 'id' + }, + unique: "employees_ibfk_1" + }, + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { + sequelize, + tableName: 'employees', + timestamps: false + }); +}; diff --git a/aws/apigateway-aurora-lambda/models/index.js b/aws/apigateway-aurora-lambda/models/index.js index 04ca42d..0736b15 100644 --- a/aws/apigateway-aurora-lambda/models/index.js +++ b/aws/apigateway-aurora-lambda/models/index.js @@ -28,8 +28,15 @@ function getDB() { ); } const uuids = require('@models/uuids'); + const employees = require('@models/employees'); + const offices = require('@models/offices'); + // eslint-disable-next-line camelcase + const employee_office = require('@models/employee_office'); db.uuids = uuids(sequelize, Sequelize.DataTypes); + db.employees = employees(sequelize, Sequelize.DataTypes); + db.offices = offices(sequelize, Sequelize.DataTypes); + db.employee_office = employee_office(sequelize, Sequelize.DataTypes); Object.keys(db).forEach(modelName => { if (db[modelName].associate) { diff --git a/aws/apigateway-aurora-lambda/models/offices.js b/aws/apigateway-aurora-lambda/models/offices.js new file mode 100644 index 0000000..9e96290 --- /dev/null +++ b/aws/apigateway-aurora-lambda/models/offices.js @@ -0,0 +1,40 @@ +/* jshint indent: 2 */ + +const Sequelize = require('sequelize'); +module.exports = function(sequelize, DataTypes) { + return sequelize.define('offices', { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + office_name: { + type: DataTypes.STRING(36), + allowNull: false, + unique: "office_name" + }, + office_address: { + type: DataTypes.STRING(36), + allowNull: false + }, + employee_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'employees', + key: 'id' + }, + unique: "offices_employee_id_fk" + }, + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { + sequelize, + tableName: 'offices', + timestamps: false + }); +}; diff --git a/aws/apigateway-aurora-lambda/models/uuids.js b/aws/apigateway-aurora-lambda/models/uuids.js index 4da659f..09ad712 100644 --- a/aws/apigateway-aurora-lambda/models/uuids.js +++ b/aws/apigateway-aurora-lambda/models/uuids.js @@ -1,26 +1,27 @@ -const moment = require('moment'); +/* jshint indent: 2 */ + +const Sequelize = require('sequelize'); module.exports = function(sequelize, DataTypes) { - return sequelize.define( - 'uuids', - { - id: { - type: DataTypes.INTEGER(11), - allowNull: true, - primaryKey: true - }, - uuid: { - type: DataTypes.STRING(36), - allowNull: false - }, - updatedAt: { - field: 'updated_at', - type: DataTypes.DATE, - allowNull: true, - defaultValue: moment().format('YYYY-MM-DD HH:mm:s:ss') - } + return sequelize.define('uuids', { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true }, - { - tableName: 'uuids' + uuid: { + type: DataTypes.STRING(36), + allowNull: false, + unique: "uuid" + }, + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') } - ); + }, { + sequelize, + tableName: 'uuids', + timestamps: false + }); }; diff --git a/aws/apigateway-aurora-lambda/serverless.yml b/aws/apigateway-aurora-lambda/serverless.yml index 0422bbd..1e57877 100644 --- a/aws/apigateway-aurora-lambda/serverless.yml +++ b/aws/apigateway-aurora-lambda/serverless.yml @@ -31,6 +31,45 @@ functions: role: LambdaRDSRole events: - http: PUT uuids + getEmployees: + handler: functions/employee/get-employees/index.handler + role: LambdaDDBRole + events: + - http: GET employees + + getEmployee: + handler: functions/employee/get-employee/index.handler + role: LambdaDDBRole + events: + - http: GET employee + + getOffices: + handler: functions/office/get-offices/index.handler + role: LambdaDDBRole + + getOffice: + handler: functions/office/get-office/index.handler + role: LambdaDDBRole + events: + - http: GET office + + putEmployee: + handler: functions/employee/put-employee/index.handler + role: LambdaDDBRole + events: + - http: PUT employee + + putOffice: + handler: functions/office/put-office/index.handler + role: LambdaDDBRole + events: + - http: PUT office + joinEmployeeAndOffice: + handler: functions/employee-office/join/index.handler + role: LambdaDDBRole + events: + - http: PUT join-employee-office + custom: scripts: hooks: @@ -41,14 +80,14 @@ custom: DB_NAME: uuids_${env:RDS_PREFIX}_${env:STAGE} resources: Resources: -# internet gateway + # internet gateway ServerlessInternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: 'Name' Value: 'ServerlessInternetGateway' -# route table + # route table RouteTablePublic: Type: AWS::EC2::RouteTable Properties: @@ -65,7 +104,7 @@ resources: Ref: ServerlessInternetGateway RouteTableId: Ref: RouteTablePublic -#route table associations + #route table associations RouteTableAssociationSubnetA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: @@ -87,7 +126,7 @@ resources: Ref: RouteTablePublic SubnetId: Ref: ServerlessSubnetC -# security group + # security group ServerlessSecurityGroup: DependsOn: - ServerlessVPC @@ -104,7 +143,7 @@ resources: Tags: - Key: 'Name' Value: 'ServerlessSecurityGroup' -# subnets + # subnets ServerlessSubnetGroup: DependsOn: - ServerlessSubnetA @@ -157,7 +196,7 @@ resources: Tags: - Key: 'Name' Value: 'ServerlessSubnetC' -# vpc + # vpc ServerlessVPC: Type: AWS::EC2::VPC Properties: @@ -175,7 +214,7 @@ resources: Ref: ServerlessVPC InternetGatewayId: Ref: ServerlessInternetGateway -# rds + # rds WednesdayRDSCluster: Type: AWS::RDS::DBCluster DependsOn: @@ -230,19 +269,19 @@ resources: Properties: Description: Managed policy to provide access to the RDS PolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - - Effect: "Allow" + - Effect: 'Allow' Action: - rds:* - Resource: "arn:aws:rds:${env:REGION}:${env:ACCOUNT_ID}:table/*_${env:RDS_PREFIX}_${env:STAGE}" + Resource: 'arn:aws:rds:${env:REGION}:${env:ACCOUNT_ID}:table/*_${env:RDS_PREFIX}_${env:STAGE}' LambdaRDSRole: Type: AWS::IAM::Role - Description: "An IAM Role to allow Lambdas to access DDB" + Description: 'An IAM Role to allow Lambdas to access DDB' Properties: RoleName: ${self:service.name}-${self:provider.stage}-lambda-ddb-role AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - Effect: Allow Action: @@ -258,4 +297,4 @@ resources: WednesdayRDSPort: Description: Port of the wednesday RDS instance Value: - Fn::GetAtt: [WednesdayRDSCluster, Endpoint.Port] \ No newline at end of file + Fn::GetAtt: [WednesdayRDSCluster, Endpoint.Port] diff --git a/aws/apigateway-aurora-lambda/setup-lambda.sh b/aws/apigateway-aurora-lambda/setup-lambda.sh new file mode 100755 index 0000000..266149c --- /dev/null +++ b/aws/apigateway-aurora-lambda/setup-lambda.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -x +# Create a lambda +npm init -y +touch index.js +touch data.json +mkdir tests +cd tests +touch index.test.js \ No newline at end of file diff --git a/aws/apigateway-aurora-lambda/utils/index.js b/aws/apigateway-aurora-lambda/utils/index.js new file mode 100644 index 0000000..6f1dfad --- /dev/null +++ b/aws/apigateway-aurora-lambda/utils/index.js @@ -0,0 +1,23 @@ +import get from 'lodash/get'; + +export const failure = (callback, error) => { + console.log('failure', error); + return callback(get(error, 'message', 'Something went wrong. Please contact support@bankshift.com')); +}; + +export const success = (callback, data) => { + console.log('success', JSON.stringify(data)); + return callback(null, data); +}; + +export const getSystemId = event => { + if (!event.headers['x-ws-system-id']) { + return null; + } + return { systemId: event.headers['x-ws-system-id'] }; +}; + +export const logHandler = (event, callback) => { + console.log(JSON.stringify({ event })); + return callback(event); +}; diff --git a/aws/apigateway-aurora-lambda/utils/testUtils.js b/aws/apigateway-aurora-lambda/utils/testUtils.js index 639e642..5ecd5e8 100644 --- a/aws/apigateway-aurora-lambda/utils/testUtils.js +++ b/aws/apigateway-aurora-lambda/utils/testUtils.js @@ -5,10 +5,43 @@ export function configDB() { const DBConnectionMock = new SequelizeMock(); const uuidsMock = DBConnectionMock.define('uuids', { uuid: CONSTANTS.uuid, updated_at: CONSTANTS.updatedAt }); + const employeesMock = DBConnectionMock.define('employees', { + employee_name: CONSTANTS.employee.employee_name, + office_id: null, + updated_at: CONSTANTS.updatedAt + }); + const officesMock = DBConnectionMock.define('offices', { + office_name: CONSTANTS.office.office_name, + office_address: CONSTANTS.office.office_address, + employee_id: null, + updated_at: CONSTANTS.updatedAt + }); + const employeeOfficeMock = DBConnectionMock.define('employee_office', { + office_name: CONSTANTS.office.office_address, + office_address: CONSTANTS.office.office_address, + employee_name: CONSTANTS.employee.employee_name, + employee_id: 1, + office_id: 1 + }); + uuidsMock.findByPk = query => uuidsMock.findById(query); uuidsMock.count = () => 1; + employeesMock.findByPk = query => employeesMock.findById(query); + employeesMock.findAll = query => employeesMock.findAll(query); + employeesMock.upsert = query => employeesMock.upsert(query); + + officesMock.findByPk = query => officesMock.findById(query); + officesMock.findAll = query => officesMock.findAll(query); + officesMock.upsert = query => officesMock.upsert(query); + + employeeOfficeMock.findAll = query => employeeOfficeMock.findAll(query); + employeeOfficeMock.upsert = query => employeeOfficeMock.upsert(query); + return { - uuids: uuidsMock + uuids: uuidsMock, + employees: employeesMock, + offices: officesMock, + employee_office: employeeOfficeMock }; } diff --git a/aws/apigateway-aurora-lambda/utils/tests/indes.test.js b/aws/apigateway-aurora-lambda/utils/tests/indes.test.js new file mode 100644 index 0000000..38b30ee --- /dev/null +++ b/aws/apigateway-aurora-lambda/utils/tests/indes.test.js @@ -0,0 +1,82 @@ +import { failure, success, logHandler, getSystemId } from '@utils'; +import { CONSTANTS } from '@mocks/constants'; +describe('utils/index', () => { + let mocks; + beforeEach(() => { + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + jest.spyOn(console, 'log'); + }); + + describe('failure', () => { + it('should print the error and invoke the callback', () => { + const error = new Error('some error'); + failure(mocks.callback, error); + + // ensure that the error is being printed + expect(console.log.mock.calls[0][0]).toBe('failure'); + expect(console.log.mock.calls[0][1]).toBe(error); + + // check if callback has been invoked + expect(mocks.callback).toBeCalled(); + + // check the parameters that have been supplied to the callback + expect(mocks.callback.mock.calls[0][0]).toBe(error.message); + expect(mocks.callback.mock.calls[0][1]).toBe(undefined); + }); + }); + + describe('success', () => { + it('should print the data and invoke the callback', () => { + const data = { otpSentAt: '123123' }; + success(mocks.callback, data); + + // ensure that the data is being printed + expect(console.log.mock.calls[0][0]).toBe('success'); + expect(console.log.mock.calls[0][1]).toBe(JSON.stringify(data)); + + // check if callback has been invoked + expect(mocks.callback).toBeCalled(); + + // check the parameters that have been supplied to callback + expect(mocks.callback.mock.calls[0][0]).toBe(null); + expect(mocks.callback.mock.calls[0][1]).toBe(data); + }); + }); + + describe('logHandler', () => { + let mocks; + beforeEach(() => { + mocks = { + callback: jest.fn() + }; + jest.spyOn(mocks, 'callback'); + }); + it('should log the event and return callback', async () => { + const mockEvent = {}; + logHandler(mockEvent, mocks.callback); + expect(mocks.callback.mock.calls.length).toBe(1); + }); + }); + + describe('getSystemId', () => { + it('should return getSystemId', async () => { + const event = { + headers: { 'x-ws-system-id': 'WS' } + }; + const response = getSystemId(event); + expect(response).toEqual({ + systemId: event.headers['x-ws-system-id'] + }); + }); + it('should return null when no auth header is present', async () => { + const event = { + headers: {} + }; + const response = getSystemId(event); + expect(response).toEqual(null); + }); + }); +}); From fb8d839e4d3bd2599ee969d50b53487974a3d677 Mon Sep 17 00:00:00 2001 From: tap0212 Date: Mon, 26 Oct 2020 13:59:05 +0530 Subject: [PATCH 2/6] resolved comments --- .../functions/employee-office/join/index.js | 8 ++++---- .../functions/employee-office/join/tests/index.test.js | 2 +- .../functions/employee/get-employees/index.js | 5 +++-- .../functions/employee/get-employees/tests/index.test.js | 2 +- .../functions/office/get-offices/index.js | 6 +++--- .../functions/office/get-offices/tests/index.test.js | 2 +- aws/apigateway-aurora-lambda/functions/uuid/put/index.js | 7 ++++--- aws/apigateway-aurora-lambda/models/index.js | 5 ++--- aws/apigateway-aurora-lambda/utils/testUtils.js | 4 ++-- 9 files changed, 21 insertions(+), 20 deletions(-) diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js b/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js index bc10f6e..b19e504 100644 --- a/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js @@ -7,10 +7,10 @@ export const handler = async (event, context, callback) => if (!getSystemId(event)) { throw new Error('Request Id Missing!'); } - console.log({ employeeId, officeId }); - const employee = await getDB().employees.findOne({ where: { id: employeeId }, raw: true }); - const office = await getDB().offices.findOne({ where: { id: officeId }, raw: true }); - const res = await getDB().employee_office.upsert({ + const { employees, offices, employeeOffice } = getDB(); + const employee = await employees.findOne({ where: { id: employeeId }, raw: true }); + const office = await offices.findOne({ where: { id: officeId }, raw: true }); + const res = await employeeOffice.upsert({ office_id: office.id, employee_id: employee.id, employee_name: employee.employee_name, diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js index fbf56df..5338ac4 100644 --- a/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js @@ -20,7 +20,7 @@ describe('join-office-employee', () => { mockDbs.offices.findOne = () => CONSTANTS.office; }); await resetAndMockDB(mockDbs => { - mockDbs.employee_office.upsert = () => true; + mockDbs.employeeOffice.upsert = () => true; }); const handler = require('../index').handler; await handler(event, null, mocks.callback); diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js index e523568..513fd62 100644 --- a/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js @@ -8,10 +8,11 @@ export const handler = async (event, context, callback) => throw new Error('Request Id Missing!'); } let res; + const { employees, employeeOffice } = getDB(); if (!officeId) { - res = await getDB().employees.findAll(); + res = await employees.findAll(); } else { - res = await getDB().employee_office.findAll({ limit, offset, where: { office_id: officeId } }); + res = await employeeOffice.findAll({ limit, offset, where: { office_id: officeId } }); } console.log(res); return success(callback, { diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js index 093de3f..90c0661 100644 --- a/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js @@ -30,7 +30,7 @@ describe('get-employees', () => { it('should fetch all employees of the given officeId', async () => { await resetAndMockDB(mockDbs => { - mockDbs.employee_office.findAll = () => [CONSTANTS.employee]; + mockDbs.employeeOffice.findAll = () => [CONSTANTS.employee]; }); const handler = require('../index').handler; await handler(event, null, mocks.callback); diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js index 7fb432c..89516c0 100644 --- a/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js @@ -8,11 +8,11 @@ export const handler = async (event, context, callback) => throw new Error('Request Id Missing!'); } let res; - console.log({ limit, offset }); + const { offices, employeeOffice } = getDB(); if (!employeeId) { - res = await getDB().offices.findAll(); + res = await offices.findAll(); } else { - res = await getDB().employee_office.findAll({ limit, offset, where: { employee_id: employeeId } }); + res = await employeeOffice.findAll({ limit, offset, where: { employee_id: employeeId } }); } return success(callback, { diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js index ef0aefd..85c5d70 100644 --- a/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js @@ -30,7 +30,7 @@ describe('get-offices', () => { it('should fetch all offices of the given employeeId', async () => { await resetAndMockDB(mockDbs => { - mockDbs.employee_office.findAll = () => [CONSTANTS.office]; + mockDbs.employeeOffice.findAll = () => [CONSTANTS.office]; }); const handler = require('../index').handler; await handler(event, null, mocks.callback); diff --git a/aws/apigateway-aurora-lambda/functions/uuid/put/index.js b/aws/apigateway-aurora-lambda/functions/uuid/put/index.js index 58e31e9..fd2685e 100644 --- a/aws/apigateway-aurora-lambda/functions/uuid/put/index.js +++ b/aws/apigateway-aurora-lambda/functions/uuid/put/index.js @@ -11,11 +11,12 @@ export const handler = async (event, context, callback) => const { uuid } = JSON.parse(event.body); const dbResponse = await getDB().uuids.findOne({ where: { uuid }, raw: true }); let newUUID; + const { uuids } = getDB(); if (dbResponse) { - await getDB().uuids.update({ updatedAt: moment() }, { where: { id: dbResponse.id } }); - newUUID = await getDB().uuids.findOne({ where: { uuid }, raw: true }); + await uuids.update({ updatedAt: moment() }, { where: { id: dbResponse.id } }); + newUUID = await uuids.findOne({ where: { uuid }, raw: true }); } else { - newUUID = await getDB().uuids.create({ uuid }); + newUUID = await uuids.create({ uuid }); } return success(callback, { status: 200, diff --git a/aws/apigateway-aurora-lambda/models/index.js b/aws/apigateway-aurora-lambda/models/index.js index 0736b15..f024515 100644 --- a/aws/apigateway-aurora-lambda/models/index.js +++ b/aws/apigateway-aurora-lambda/models/index.js @@ -30,13 +30,12 @@ function getDB() { const uuids = require('@models/uuids'); const employees = require('@models/employees'); const offices = require('@models/offices'); - // eslint-disable-next-line camelcase - const employee_office = require('@models/employee_office'); + const employeeOffice = require('@models/employee_office'); db.uuids = uuids(sequelize, Sequelize.DataTypes); db.employees = employees(sequelize, Sequelize.DataTypes); db.offices = offices(sequelize, Sequelize.DataTypes); - db.employee_office = employee_office(sequelize, Sequelize.DataTypes); + db.employeeOffice = employeeOffice(sequelize, Sequelize.DataTypes); Object.keys(db).forEach(modelName => { if (db[modelName].associate) { diff --git a/aws/apigateway-aurora-lambda/utils/testUtils.js b/aws/apigateway-aurora-lambda/utils/testUtils.js index 5ecd5e8..1903872 100644 --- a/aws/apigateway-aurora-lambda/utils/testUtils.js +++ b/aws/apigateway-aurora-lambda/utils/testUtils.js @@ -16,7 +16,7 @@ export function configDB() { employee_id: null, updated_at: CONSTANTS.updatedAt }); - const employeeOfficeMock = DBConnectionMock.define('employee_office', { + const employeeOfficeMock = DBConnectionMock.define('employeeOffice', { office_name: CONSTANTS.office.office_address, office_address: CONSTANTS.office.office_address, employee_name: CONSTANTS.employee.employee_name, @@ -41,7 +41,7 @@ export function configDB() { uuids: uuidsMock, employees: employeesMock, offices: officesMock, - employee_office: employeeOfficeMock + employeeOffice: employeeOfficeMock }; } From d416a91d426806548b389a41062ba5ca9d8010b6 Mon Sep 17 00:00:00 2001 From: tap0212 Date: Tue, 27 Oct 2020 16:39:46 +0530 Subject: [PATCH 3/6] hotfix --- .../__mocks__/constants.js | 4 + .../functions/employee-office/join/index.js | 14 ++-- .../employee-office/join/tests/index.test.js | 8 +- .../functions/employee/get-employees/index.js | 17 +++- .../get-employees/tests/index.test.js | 6 +- .../functions/office/get-offices/index.js | 17 +++- .../office/get-offices/tests/index.test.js | 6 +- .../resources/v1/04_employee_office.sql | 4 +- .../models/employee_office.js | 78 ++++++++----------- .../utils/testUtils.js | 1 + 10 files changed, 77 insertions(+), 78 deletions(-) diff --git a/aws/apigateway-aurora-lambda/__mocks__/constants.js b/aws/apigateway-aurora-lambda/__mocks__/constants.js index 2652468..7a7d363 100644 --- a/aws/apigateway-aurora-lambda/__mocks__/constants.js +++ b/aws/apigateway-aurora-lambda/__mocks__/constants.js @@ -20,3 +20,7 @@ export const CONSTANTS = { updated_at: '2020-10-25T16:01:55.000Z' } }; +export const GET_EMP_BY_OFF_ID = + '{"res":{"employeeList":[{"office_name":"Wednesday Solutions","office_address":"Pune, MH, India","employee_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}],"office":{"office_name":"Wednesday Solutions","office_address":"Pune, MH, India","employee_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}}}'; +export const GET_OFF_BY_EMP_ID = + '{"res":{"officeList":[{"office_name":"Wednesday Solutions","office_address":"Pune, MH, India","employee_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}],"employee":{"employee_name":"Tapan","office_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}}}'; diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js b/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js index b19e504..2026053 100644 --- a/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/index.js @@ -7,15 +7,11 @@ export const handler = async (event, context, callback) => if (!getSystemId(event)) { throw new Error('Request Id Missing!'); } - const { employees, offices, employeeOffice } = getDB(); - const employee = await employees.findOne({ where: { id: employeeId }, raw: true }); - const office = await offices.findOne({ where: { id: officeId }, raw: true }); - const res = await employeeOffice.upsert({ - office_id: office.id, - employee_id: employee.id, - employee_name: employee.employee_name, - office_name: office.office_name, - office_address: office.office_address + const { employeeOffice } = getDB(); + + const res = await employeeOffice.create({ + office_id: officeId, + employee_id: employeeId }); return success(callback, { status: 200, diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js index 5338ac4..e31f82a 100644 --- a/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js @@ -14,13 +14,7 @@ describe('join-office-employee', () => { }); it('should update/put an employee', async () => { await resetAndMockDB(mockDbs => { - mockDbs.employees.findOne = () => CONSTANTS.employee; - }); - await resetAndMockDB(mockDbs => { - mockDbs.offices.findOne = () => CONSTANTS.office; - }); - await resetAndMockDB(mockDbs => { - mockDbs.employeeOffice.upsert = () => true; + mockDbs.employeeOffice.create = () => true; }); const handler = require('../index').handler; await handler(event, null, mocks.callback); diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js index 513fd62..bfd2c94 100644 --- a/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js @@ -8,13 +8,24 @@ export const handler = async (event, context, callback) => throw new Error('Request Id Missing!'); } let res; - const { employees, employeeOffice } = getDB(); + const employeeList = []; + + const { offices, employeeOffice, employees } = getDB(); if (!officeId) { res = await employees.findAll(); } else { - res = await employeeOffice.findAll({ limit, offset, where: { office_id: officeId } }); + const employeeOfficeRes = await employeeOffice.findAll({ limit, offset, where: { office_id: officeId } }); + await Promise.all( + employeeOfficeRes.map(async e => { + employeeList.push(await offices.findOne({ where: { id: e.dataValues.office_id }, raw: true })); + }) + ); + res = { + employeeList, + office: await offices.findOne({ where: { id: officeId }, raw: true }) + }; } - console.log(res); + console.log({ '####': JSON.stringify({ res }) }); return success(callback, { status: 200, body: JSON.stringify({ res }) diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js index 90c0661..fe33f24 100644 --- a/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/tests/index.test.js @@ -1,4 +1,4 @@ -import { CONSTANTS } from '@mocks/constants'; +import { CONSTANTS, GET_EMP_BY_OFF_ID } from '@mocks/constants'; import { resetAndMockDB } from '@utils/testUtils'; describe('get-employees', () => { @@ -30,7 +30,7 @@ describe('get-employees', () => { it('should fetch all employees of the given officeId', async () => { await resetAndMockDB(mockDbs => { - mockDbs.employeeOffice.findAll = () => [CONSTANTS.employee]; + mockDbs.employeeOffice.findAll = () => [{ dataValues: CONSTANTS.employee }]; }); const handler = require('../index').handler; await handler(event, null, mocks.callback); @@ -39,7 +39,7 @@ describe('get-employees', () => { expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); expect(mocks.callback.mock.calls[0][1]).toEqual({ status: 200, - body: JSON.stringify({ res: [CONSTANTS.employee] }) + body: GET_EMP_BY_OFF_ID }); }); diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js index 89516c0..f99a539 100644 --- a/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js @@ -8,13 +8,24 @@ export const handler = async (event, context, callback) => throw new Error('Request Id Missing!'); } let res; - const { offices, employeeOffice } = getDB(); + const officeList = []; + + const { offices, employeeOffice, employees } = getDB(); if (!employeeId) { res = await offices.findAll(); } else { - res = await employeeOffice.findAll({ limit, offset, where: { employee_id: employeeId } }); + const employeeOfficeRes = await employeeOffice.findAll({ limit, offset, where: { employee_id: employeeId } }); + await Promise.all( + employeeOfficeRes.map(async e => { + officeList.push(await offices.findOne({ where: { id: e.dataValues.office_id }, raw: true })); + }) + ); + res = { + officeList, + employee: await employees.findOne({ where: { id: employeeId }, raw: true }) + }; } - + console.log({ '###': JSON.stringify({ res }) }); return success(callback, { status: 200, body: JSON.stringify({ res }) diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js index 85c5d70..ebef0eb 100644 --- a/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/tests/index.test.js @@ -1,4 +1,4 @@ -import { CONSTANTS } from '@mocks/constants'; +import { CONSTANTS, GET_OFF_BY_EMP_ID } from '@mocks/constants'; import { resetAndMockDB } from '@utils/testUtils'; describe('get-offices', () => { @@ -30,7 +30,7 @@ describe('get-offices', () => { it('should fetch all offices of the given employeeId', async () => { await resetAndMockDB(mockDbs => { - mockDbs.employeeOffice.findAll = () => [CONSTANTS.office]; + mockDbs.employeeOffice.findAll = () => [{ dataValues: CONSTANTS.office }]; }); const handler = require('../index').handler; await handler(event, null, mocks.callback); @@ -39,7 +39,7 @@ describe('get-offices', () => { expect(mocks.callback.mock.calls[0][1]).toBeTruthy(); expect(mocks.callback.mock.calls[0][1]).toEqual({ status: 200, - body: JSON.stringify({ res: [CONSTANTS.office] }) + body: GET_OFF_BY_EMP_ID }); }); diff --git a/aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql b/aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql index 8986481..ee4ef0c 100644 --- a/aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql +++ b/aws/apigateway-aurora-lambda/migrations/resources/v1/04_employee_office.sql @@ -1,11 +1,9 @@ create table employee_office ( id INT PRIMARY KEY AUTO_INCREMENT, - office_name VARCHAR(36) NOT NULL, - office_address VARCHAR(36) NOT NULL, - employee_name VARCHAR(36) NOT NULL, employee_id INT NOT NULL, office_id INT NOT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT employee_office_id UNIQUE (id), CONSTRAINT employee_id_fk FOREIGN KEY (employee_id) REFERENCES employees (id), CONSTRAINT office_id_fk FOREIGN KEY (office_id) REFERENCES offices (id) ); \ No newline at end of file diff --git a/aws/apigateway-aurora-lambda/models/employee_office.js b/aws/apigateway-aurora-lambda/models/employee_office.js index e6fa73c..7d66e98 100644 --- a/aws/apigateway-aurora-lambda/models/employee_office.js +++ b/aws/apigateway-aurora-lambda/models/employee_office.js @@ -2,55 +2,39 @@ const Sequelize = require('sequelize'); module.exports = function(sequelize, DataTypes) { - return sequelize.define( - 'employee_office', - { - id: { - autoIncrement: true, - type: DataTypes.INTEGER, - allowNull: false, - primaryKey: true - }, - office_name: { - type: DataTypes.STRING(36), - allowNull: false - }, - office_address: { - type: DataTypes.STRING(36), - allowNull: false - }, - employee_name: { - type: DataTypes.STRING(36), - allowNull: false - }, - employee_id: { - type: DataTypes.INTEGER, - allowNull: false, - references: { - model: 'employees', - key: 'id' - }, - unique: 'employee_id_fk' + return sequelize.define('employee_office', { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + employee_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'employees', + key: 'id' }, - office_id: { - type: DataTypes.INTEGER, - allowNull: false, - references: { - model: 'offices', - key: 'id' - }, - unique: 'office_id_fk' + unique: "employee_id_fk" + }, + office_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'offices', + key: 'id' }, - updated_at: { - type: DataTypes.DATE, - allowNull: true, - defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') - } + unique: "office_id_fk" }, - { - sequelize, - tableName: 'employee_office', - timestamps: false + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') } - ); + }, { + sequelize, + tableName: 'employee_office', + timestamps: false + }); }; diff --git a/aws/apigateway-aurora-lambda/utils/testUtils.js b/aws/apigateway-aurora-lambda/utils/testUtils.js index 1903872..affee00 100644 --- a/aws/apigateway-aurora-lambda/utils/testUtils.js +++ b/aws/apigateway-aurora-lambda/utils/testUtils.js @@ -36,6 +36,7 @@ export function configDB() { employeeOfficeMock.findAll = query => employeeOfficeMock.findAll(query); employeeOfficeMock.upsert = query => employeeOfficeMock.upsert(query); + employeeOfficeMock.create = query => employeeOfficeMock.create(query); return { uuids: uuidsMock, From 593d9e834e7e27a667e3753dcc3eafa1cf991fe1 Mon Sep 17 00:00:00 2001 From: tap0212 Date: Tue, 27 Oct 2020 17:05:38 +0530 Subject: [PATCH 4/6] hotfix --- aws/apigateway-aurora-lambda/__mocks__/constants.js | 2 +- .../functions/employee/get-employees/index.js | 3 +-- .../functions/office/get-offices/index.js | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/aws/apigateway-aurora-lambda/__mocks__/constants.js b/aws/apigateway-aurora-lambda/__mocks__/constants.js index 7a7d363..0fa657a 100644 --- a/aws/apigateway-aurora-lambda/__mocks__/constants.js +++ b/aws/apigateway-aurora-lambda/__mocks__/constants.js @@ -21,6 +21,6 @@ export const CONSTANTS = { } }; export const GET_EMP_BY_OFF_ID = - '{"res":{"employeeList":[{"office_name":"Wednesday Solutions","office_address":"Pune, MH, India","employee_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}],"office":{"office_name":"Wednesday Solutions","office_address":"Pune, MH, India","employee_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}}}'; + '{"res":{"employeeList":[{"employee_name":"Tapan","office_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}],"office":{"office_name":"Wednesday Solutions","office_address":"Pune, MH, India","employee_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}}}'; export const GET_OFF_BY_EMP_ID = '{"res":{"officeList":[{"office_name":"Wednesday Solutions","office_address":"Pune, MH, India","employee_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}],"employee":{"employee_name":"Tapan","office_id":null,"updated_at":"2000-11-22 05:30:0:00","id":1,"createdAt":"2000-11-22T00:00:00.000Z","updatedAt":"2000-11-22T00:00:00.000Z"}}}'; diff --git a/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js index bfd2c94..4669df0 100644 --- a/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js +++ b/aws/apigateway-aurora-lambda/functions/employee/get-employees/index.js @@ -17,7 +17,7 @@ export const handler = async (event, context, callback) => const employeeOfficeRes = await employeeOffice.findAll({ limit, offset, where: { office_id: officeId } }); await Promise.all( employeeOfficeRes.map(async e => { - employeeList.push(await offices.findOne({ where: { id: e.dataValues.office_id }, raw: true })); + employeeList.push(await employees.findOne({ where: { id: e.dataValues.employee_id }, raw: true })); }) ); res = { @@ -25,7 +25,6 @@ export const handler = async (event, context, callback) => office: await offices.findOne({ where: { id: officeId }, raw: true }) }; } - console.log({ '####': JSON.stringify({ res }) }); return success(callback, { status: 200, body: JSON.stringify({ res }) diff --git a/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js index f99a539..1c42ee5 100644 --- a/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js +++ b/aws/apigateway-aurora-lambda/functions/office/get-offices/index.js @@ -25,7 +25,6 @@ export const handler = async (event, context, callback) => employee: await employees.findOne({ where: { id: employeeId }, raw: true }) }; } - console.log({ '###': JSON.stringify({ res }) }); return success(callback, { status: 200, body: JSON.stringify({ res }) From 522eadbadd7930895f9224630c91cd60cdb2ee02 Mon Sep 17 00:00:00 2001 From: tap0212 Date: Tue, 27 Oct 2020 17:34:56 +0530 Subject: [PATCH 5/6] fixed linting issues --- .../employee-office/join/tests/index.test.js | 1 - .../models/employee_office.js | 66 +++++++++--------- .../models/employees.js | 60 ++++++++-------- .../models/offices.js | 68 ++++++++++--------- aws/apigateway-aurora-lambda/models/uuids.js | 44 ++++++------ .../utils/tests/indes.test.js | 1 - 6 files changed, 127 insertions(+), 113 deletions(-) diff --git a/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js index e31f82a..7e7bcce 100644 --- a/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/employee-office/join/tests/index.test.js @@ -1,5 +1,4 @@ import { resetAndMockDB } from '@utils/testUtils'; -import { CONSTANTS } from '@mocks/constants'; describe('join-office-employee', () => { let event; diff --git a/aws/apigateway-aurora-lambda/models/employee_office.js b/aws/apigateway-aurora-lambda/models/employee_office.js index 7d66e98..0ef8025 100644 --- a/aws/apigateway-aurora-lambda/models/employee_office.js +++ b/aws/apigateway-aurora-lambda/models/employee_office.js @@ -2,39 +2,43 @@ const Sequelize = require('sequelize'); module.exports = function(sequelize, DataTypes) { - return sequelize.define('employee_office', { - id: { - autoIncrement: true, - type: DataTypes.INTEGER, - allowNull: false, - primaryKey: true - }, - employee_id: { - type: DataTypes.INTEGER, - allowNull: false, - references: { - model: 'employees', - key: 'id' + return sequelize.define( + 'employee_office', + { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true }, - unique: "employee_id_fk" - }, - office_id: { - type: DataTypes.INTEGER, - allowNull: false, - references: { - model: 'offices', - key: 'id' + employee_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'employees', + key: 'id' + }, + unique: 'employee_id_fk' + }, + office_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'offices', + key: 'id' + }, + unique: 'office_id_fk' }, - unique: "office_id_fk" + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } }, - updated_at: { - type: DataTypes.DATE, - allowNull: true, - defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + { + sequelize, + tableName: 'employee_office', + timestamps: false } - }, { - sequelize, - tableName: 'employee_office', - timestamps: false - }); + ); }; diff --git a/aws/apigateway-aurora-lambda/models/employees.js b/aws/apigateway-aurora-lambda/models/employees.js index 17c18cf..39c469a 100644 --- a/aws/apigateway-aurora-lambda/models/employees.js +++ b/aws/apigateway-aurora-lambda/models/employees.js @@ -2,35 +2,39 @@ const Sequelize = require('sequelize'); module.exports = function(sequelize, DataTypes) { - return sequelize.define('employees', { - id: { - autoIncrement: true, - type: DataTypes.INTEGER, - allowNull: false, - primaryKey: true - }, - employee_name: { - type: DataTypes.STRING(36), - allowNull: false, - unique: "employee_name" - }, - office_id: { - type: DataTypes.INTEGER, - allowNull: true, - references: { - model: 'offices', - key: 'id' + return sequelize.define( + 'employees', + { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + employee_name: { + type: DataTypes.STRING(36), + allowNull: false, + unique: 'employee_name' + }, + office_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'offices', + key: 'id' + }, + unique: 'employees_ibfk_1' }, - unique: "employees_ibfk_1" + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } }, - updated_at: { - type: DataTypes.DATE, - allowNull: true, - defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + { + sequelize, + tableName: 'employees', + timestamps: false } - }, { - sequelize, - tableName: 'employees', - timestamps: false - }); + ); }; diff --git a/aws/apigateway-aurora-lambda/models/offices.js b/aws/apigateway-aurora-lambda/models/offices.js index 9e96290..f8de38e 100644 --- a/aws/apigateway-aurora-lambda/models/offices.js +++ b/aws/apigateway-aurora-lambda/models/offices.js @@ -2,39 +2,43 @@ const Sequelize = require('sequelize'); module.exports = function(sequelize, DataTypes) { - return sequelize.define('offices', { - id: { - autoIncrement: true, - type: DataTypes.INTEGER, - allowNull: false, - primaryKey: true - }, - office_name: { - type: DataTypes.STRING(36), - allowNull: false, - unique: "office_name" - }, - office_address: { - type: DataTypes.STRING(36), - allowNull: false - }, - employee_id: { - type: DataTypes.INTEGER, - allowNull: true, - references: { - model: 'employees', - key: 'id' + return sequelize.define( + 'offices', + { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + office_name: { + type: DataTypes.STRING(36), + allowNull: false, + unique: 'office_name' + }, + office_address: { + type: DataTypes.STRING(36), + allowNull: false + }, + employee_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'employees', + key: 'id' + }, + unique: 'offices_employee_id_fk' }, - unique: "offices_employee_id_fk" + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } }, - updated_at: { - type: DataTypes.DATE, - allowNull: true, - defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + { + sequelize, + tableName: 'offices', + timestamps: false } - }, { - sequelize, - tableName: 'offices', - timestamps: false - }); + ); }; diff --git a/aws/apigateway-aurora-lambda/models/uuids.js b/aws/apigateway-aurora-lambda/models/uuids.js index 09ad712..265eb72 100644 --- a/aws/apigateway-aurora-lambda/models/uuids.js +++ b/aws/apigateway-aurora-lambda/models/uuids.js @@ -2,26 +2,30 @@ const Sequelize = require('sequelize'); module.exports = function(sequelize, DataTypes) { - return sequelize.define('uuids', { - id: { - autoIncrement: true, - type: DataTypes.INTEGER, - allowNull: false, - primaryKey: true + return sequelize.define( + 'uuids', + { + id: { + autoIncrement: true, + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true + }, + uuid: { + type: DataTypes.STRING(36), + allowNull: false, + unique: 'uuid' + }, + updated_at: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } }, - uuid: { - type: DataTypes.STRING(36), - allowNull: false, - unique: "uuid" - }, - updated_at: { - type: DataTypes.DATE, - allowNull: true, - defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + { + sequelize, + tableName: 'uuids', + timestamps: false } - }, { - sequelize, - tableName: 'uuids', - timestamps: false - }); + ); }; diff --git a/aws/apigateway-aurora-lambda/utils/tests/indes.test.js b/aws/apigateway-aurora-lambda/utils/tests/indes.test.js index 38b30ee..8dbd393 100644 --- a/aws/apigateway-aurora-lambda/utils/tests/indes.test.js +++ b/aws/apigateway-aurora-lambda/utils/tests/indes.test.js @@ -1,5 +1,4 @@ import { failure, success, logHandler, getSystemId } from '@utils'; -import { CONSTANTS } from '@mocks/constants'; describe('utils/index', () => { let mocks; beforeEach(() => { From 1135f2bb476f1d41bd3d2a973274165047145aba Mon Sep 17 00:00:00 2001 From: tap0212 Date: Tue, 27 Oct 2020 19:20:19 +0530 Subject: [PATCH 6/6] hotfix console logs --- .../functions/office/get-office/index.js | 1 - .../functions/uuid/get/tests/index.test.js | 1 - 2 files changed, 2 deletions(-) diff --git a/aws/apigateway-aurora-lambda/functions/office/get-office/index.js b/aws/apigateway-aurora-lambda/functions/office/get-office/index.js index 2186d62..1402434 100644 --- a/aws/apigateway-aurora-lambda/functions/office/get-office/index.js +++ b/aws/apigateway-aurora-lambda/functions/office/get-office/index.js @@ -8,7 +8,6 @@ export const handler = async (event, context, callback) => throw new Error('Request Id Missing!'); } const res = await getDB().offices.findOne({ where: { id: officeId }, raw: true }); - console.log({ res }); return success(callback, { status: 200, body: JSON.stringify({ res }) diff --git a/aws/apigateway-aurora-lambda/functions/uuid/get/tests/index.test.js b/aws/apigateway-aurora-lambda/functions/uuid/get/tests/index.test.js index f2fbbcf..70b8001 100644 --- a/aws/apigateway-aurora-lambda/functions/uuid/get/tests/index.test.js +++ b/aws/apigateway-aurora-lambda/functions/uuid/get/tests/index.test.js @@ -4,7 +4,6 @@ describe('get-uuid', () => { it('should get a new UUID', async () => { const response = await handler(); const body = JSON.parse(response.body); - console.log({ body }); expect(body.uuid).toEqual(CONSTANTS.uuid); }); });