diff --git a/src/functions/create/handler.ts b/src/functions/create/handler.ts index ac63f5d..030ab8b 100644 --- a/src/functions/create/handler.ts +++ b/src/functions/create/handler.ts @@ -7,6 +7,8 @@ import schema from './schema'; import { MongoDB } from '../../util'; import * as config from '../../config'; +import { validateEmail } from '../../helper'; + import * as path from 'path'; import * as dotenv from 'dotenv'; dotenv.config({ path: path.resolve(process.cwd(), '.env') }); @@ -25,6 +27,15 @@ const create: ValidatedEventAPIGatewayProxyEvent = async (event) } const uEmail = event.body.email.toLowerCase(); + if (!validateEmail(uEmail)) { + return { + statusCode: 403, + body: JSON.stringify({ + statusCode: 403, + message: 'Improper Email format', + }), + }; + } let password = event.body.password; try { diff --git a/src/functions/update-buy-ins/handler.ts b/src/functions/update-buy-ins/handler.ts index b047998..fa4f269 100644 --- a/src/functions/update-buy-ins/handler.ts +++ b/src/functions/update-buy-ins/handler.ts @@ -79,6 +79,32 @@ const updateBuyIns: ValidatedEventAPIGatewayProxyEvent = async (e }; } + //validate point update + for (const userBuyIn of userBuyInsSorted) { + const value = userBuyIn.buy_in; + if (value === '') userBuyIn.buy_in = 0; + + const numVal = parseInt(value, 10); + if (Number.isNaN(numVal)) { + return { + statusCode: 403, + body: JSON.stringify({ + statusCode: 403, + message: 'Requested point change is not a valid integer input', + }), + }; + } + if (numVal >= 1000 || numVal <= -1000) { + return { + statusCode: 403, + body: JSON.stringify({ + statusCode: 403, + message: 'Requested point change is not in a valid point range', + }), + }; + } + } + //update the buy_ins array await pointCollection.updateOne({ email: event.body.email }, { $set: { buy_ins: event.body.buy_ins } }); return { diff --git a/src/functions/update/handler.ts b/src/functions/update/handler.ts index 2262233..c5e1c00 100644 --- a/src/functions/update/handler.ts +++ b/src/functions/update/handler.ts @@ -4,6 +4,8 @@ import { middyfy } from '@libs/lambda'; import schema from './schema'; +import { validateEmail } from '../../helper'; + import { MongoDB, validateToken, ensureRoles } from '../../util'; import * as path from 'path'; import * as dotenv from 'dotenv'; @@ -214,6 +216,9 @@ function validateUpdates(updates: Updates, registrationStatus?: string, user?: W return 'Missing required fields'; } else return true; } + + if ('email' in setUpdates) if (!validateEmail(setUpdates.email)) return 'Improper Email format'; + if ( ['_id', 'password', 'discord', 'created_at', 'registered_at', 'email_verified'].some( (lockedProp) => lockedProp in setUpdates diff --git a/src/helper.ts b/src/helper.ts new file mode 100644 index 0000000..eda2531 --- /dev/null +++ b/src/helper.ts @@ -0,0 +1,4 @@ +export function validateEmail(email) { + const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailPattern.test(email); +} diff --git a/tests/create.test.ts b/tests/create.test.ts index f42b548..57de15e 100644 --- a/tests/create.test.ts +++ b/tests/create.test.ts @@ -48,6 +48,17 @@ describe('Create endpoint', () => { expect(res.statusCode).toBe(200); expect(JSON.parse(res.body).message).toBe('User created!'); }); + it('Email entry is invalid', async () => { + const mockEvent = createEvent({ email: 'notValidFormat', password: 'testPassword123' }, '/create', 'POST'); + + const mockCallback = jest.fn(); + + (bcrypt.hash as jest.Mock).mockResolvedValue('hashedPassword'); + const res = await main(mockEvent, mockContext, mockCallback); + + expect(res.statusCode).toBe(403); + expect(JSON.parse(res.body).message).toBe('Improper Email format'); + }); it('Registration time has passed', async () => { jest.useFakeTimers(); jest.setSystemTime(new Date('01/01/2100')); diff --git a/tests/update-buy-ins.test.ts b/tests/update-buy-ins.test.ts index 39449e5..b54e04d 100644 --- a/tests/update-buy-ins.test.ts +++ b/tests/update-buy-ins.test.ts @@ -96,8 +96,45 @@ describe('Update-Buy-Ins tests', () => { expect(result.statusCode).toBe(403); expect(JSON.parse(result.body).message).toBe('Points distributed exceed user point total.'); }); + //case 5 + it('non-numeric value entered for input', async () => { + findOneMock.mockReturnValueOnce({ + email: userData.email, + total_points: 30, + balance: 2, + buy_ins: [ + { prize_id: 'prize1', buy_in: 'random' }, + { prize_id: 'prize2', buy_in: 20 }, + ], + }); - // case 5 + const mockEvent = createEvent(userData, path, httpMethod); + + const result = await main(mockEvent, mockContext, mockCallback); + + expect(result.statusCode).toBe(403); + expect(JSON.parse(result.body).message).toBe('Requested point change is not a valid integer input'); + }); + // case 6 + it('Buy-in points out of range', async () => { + findOneMock.mockReturnValueOnce({ + email: userData.email, + total_points: 30, + balance: 2, + buy_ins: [ + { prize_id: 'prize1', buy_in: 1500 }, + { prize_id: 'prize2', buy_in: 20 }, + ], + }); + + const mockEvent = createEvent(userData, path, httpMethod); + + const result = await main(mockEvent, mockContext, mockCallback); + + expect(result.statusCode).toBe(403); + expect(JSON.parse(result.body).message).toBe('Requested point change is not in a valid point range'); + }); + // case 7 it('successfully update user point balance', async () => { findOneMock.mockReturnValueOnce({ email: userData.email, diff --git a/tests/update.test.ts b/tests/update.test.ts index cf038e1..c77426b 100644 --- a/tests/update.test.ts +++ b/tests/update.test.ts @@ -261,6 +261,7 @@ describe('/update endpoint', () => { }, }, }; + jest.clearAllMocks(); findOneMock.mockReturnValue({ //successful update @@ -298,4 +299,21 @@ describe('/update endpoint', () => { const res = await main(mockEvent, mockContext, mockCallback); expect(res.statusCode).toBe(200); }); + //case 9 + it('Invalid email format', async () => { + const completeUserData = { + user_email: 'test@test.org', + auth_email: 'testAuth@test.org', + auth_token: 'sampleAuthToken', + updates: { + $set: { + email: 'randomVal', + }, + }, + }; + const mockEvent = createEvent(completeUserData, '/update', 'POST'); + const res = await main(mockEvent, mockContext, mockCallback); + expect(res.statusCode).toBe(400); + expect(JSON.parse(res.body).message).toBe('Improper Email format'); + }); });