-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
User service: login, registration, graphql completion (#3)
* user schema, abstract dynamo db class, user integration test * completed integration test suite * delete test cleanup * user GQL service integration, start spec for user schema, service connection to gql middleware * - dynamic config/environment support - ddb abstract support of environments - sls pseudo parameters for env support - debugging cleanup - tsconfig es2018 update (prep for type-graphql) * mocha cli testing, actions * testing workflow * testing workflow * adding package-lock * workflow testing step * join build/test jobs * re-naming workflow * user route/svc, login/mfa/oob methods, correct error handling, a0 envvars through ssm * user service static method tests, http wrapper tests, updated env support for user svc * rolling back router response type change * user registration consolidation to graph endpoint, code cleanup, strict type checking on graph endpoint * update content-type for graph requests to json * - updated test cases to account for user svc updates - user svc field requirement testing testing (email, sub, phone) - user svc email field regex - user svc sub format to follow A0 (database<type>|uuid) - user svc phone number to support U.S. prefix/format only - user schema write now requires (email, phone, sub) - user schema marshaller createdAt correction - user route query payload regex correction * user svc validation refactor, PR feedback interation * email field regex update, fix for missing phone field in payload, updated test cases * no unused var fix * - completed user registration flow - refactored user authentication flow - user mfa verification flow, post registration
- Loading branch information
1 parent
5ec5e46
commit 5a85115
Showing
38 changed files
with
810 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
|
||
const sinon = require('sinon'); | ||
|
||
import { expect } from 'chai'; | ||
|
||
import { httpWrapper as https } from '@services/http'; | ||
|
||
describe('http', () => { | ||
const sandbox = sinon.createSandbox(); | ||
|
||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
|
||
describe('get', () => { | ||
it('promise should resolve', async () => { | ||
let request; | ||
const klass = new https('foo.bar'); | ||
sandbox.stub(klass, 'get').resolves(true); | ||
|
||
try { | ||
request = await klass.get('/baz'); | ||
console.log(request); | ||
} catch (error) { | ||
console.log(error); | ||
} finally { | ||
expect(request).to.equal(true); | ||
} | ||
}); | ||
|
||
it('promise should reject', async () => { | ||
let request; | ||
const klass = new https('foo.bar'); | ||
sandbox.stub(klass, 'get').rejects(false); | ||
|
||
try { | ||
request = await klass.get('/baz'); | ||
console.log(request); | ||
} catch (error) { | ||
console.log(error); | ||
expect(request).to.have.throw; | ||
} | ||
}); | ||
}); | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,7 @@ import { expect } from 'chai'; | |
import { User } from '@services/user'; | ||
|
||
describe.skip('user', () => { | ||
let klass; | ||
let payload; | ||
let klass, payload; | ||
|
||
const sandbox = sinon.createSandbox(); | ||
|
||
|
@@ -16,7 +15,7 @@ describe.skip('user', () => { | |
}); | ||
|
||
beforeEach(function(done) { | ||
payload = { email: '[email protected]', sub: +new Date() }; | ||
payload = { email: '[email protected]', phone: '+19995551111' }; | ||
klass = new User(); | ||
|
||
const tableExists = klass.ensureTableExists(); | ||
|
@@ -29,9 +28,9 @@ describe.skip('user', () => { | |
|
||
describe('delete', () => { | ||
it('should delete record', (done) => { | ||
const payload = { email: '[email protected]', sub: +new Date() }; | ||
const payload = { email: '[email protected]', phone: '+19995551111' }; | ||
const put = klass.execute('put', payload); | ||
const del = klass.execute('delete', payload) | ||
const del = klass.execute('delete', { email: payload.email }); | ||
|
||
Promise.all([put, del]).then(results => { | ||
expect(results[results.length - 1].email).to.equal(payload.email); | ||
|
@@ -40,12 +39,10 @@ describe.skip('user', () => { | |
}); | ||
|
||
it('should return error', async () => { | ||
const payload = { foo: '[email protected]', sub: +new Date() }; | ||
|
||
try { | ||
await klass.execute('delete', payload); | ||
await klass.execute('delete', { foo: 'bar@baz' }); | ||
} catch (error) { | ||
expect(error.code).to.equal('ValidationException'); | ||
expect(error.message).to.equal('Field does not match requirements: [email, undefined]'); | ||
} | ||
}); | ||
}); | ||
|
@@ -67,7 +64,7 @@ describe.skip('user', () => { | |
}); | ||
|
||
describe('get', () => { | ||
it('should return record', async () => { | ||
it('should return record by full payload', async () => { | ||
let record; | ||
|
||
try { | ||
|
@@ -80,47 +77,109 @@ describe.skip('user', () => { | |
expect(record.email).to.equal(payload.email); | ||
}); | ||
|
||
it('should return error', async () => { | ||
it('should return record by email', async () => { | ||
let record; | ||
const p = { email: '[email protected]' }; | ||
|
||
try { | ||
record = await klass.execute('get', p); | ||
} catch (error) { | ||
console.log(error); | ||
return; | ||
} | ||
|
||
expect(record.email).to.equal(payload.email); | ||
}); | ||
|
||
it('should return error due to no valid parameters', async () => { | ||
const payload = { foo: 'bar' }; | ||
|
||
try { | ||
await klass.execute('get', payload); | ||
} catch (error) { | ||
expect(error.code).to.equal('ValidationException'); | ||
expect(error.message).to.equal('Field does not match requirements: [email, undefined]'); | ||
} | ||
}); | ||
}); | ||
|
||
describe('put', () => { | ||
it('should write record', async () => { | ||
let record; | ||
const email = 'baz@bar.foo'; | ||
const sub = +new Date(); | ||
const email = 'foo@bar.baz'; | ||
const phone = '+19995551111'; | ||
|
||
try { | ||
record = await klass.execute('put', { email: email, sub: sub }); | ||
record = await klass.execute('put', { email, phone }); | ||
} catch (error) { | ||
console.log(error); | ||
return; | ||
console.error(error); | ||
} | ||
|
||
expect(record.email).to.equal(email); | ||
}); | ||
|
||
it('should violate email format requirement', async () => { | ||
let record; | ||
const email = 'baz@bar'; | ||
const phone = '+19995551111'; | ||
|
||
try { | ||
record = await klass.execute('put', { email, phone }); | ||
} catch (error) { | ||
expect(error.message).to.equal(`Field does not match requirements: [email, ${email}]`); | ||
} | ||
|
||
console.log(record); | ||
}); | ||
|
||
it('should violate phone format requirement', async () => { | ||
const email = '[email protected]'; | ||
const phone = '+828282'; | ||
|
||
try { | ||
await klass.execute('put', { email, phone }); | ||
} catch (error) { | ||
console.log(error); | ||
expect(error.message).to.equal(`Field does not match requirements: [phone, ${phone}]`); | ||
} | ||
}); | ||
}); | ||
|
||
describe('update', () => { | ||
it('should update record', async () => { | ||
let record; | ||
const sub = +new Date(); | ||
const phone = '+10005551111'; | ||
const sub = 'test|0987654321'; | ||
|
||
try { | ||
record = await klass.execute('update', { email: payload.email, sub: sub }); | ||
record = await klass.execute('update', { email: payload.email, phone, sub }); | ||
} catch (error) { | ||
console.log(error); | ||
return; | ||
} | ||
|
||
expect(record.sub).to.equal(sub.toString()); | ||
}); | ||
|
||
it('should violate phone requirement', async () => { | ||
const sub = 'test|1234567890'; | ||
|
||
try { | ||
await klass.execute('update', { email: payload.email, sub }); | ||
} catch (error) { | ||
console.log(error); | ||
expect(error.message).to.equal(`Field does not match requirements: [phone, undefined]`); | ||
} | ||
}); | ||
|
||
it('should violate sub requirement', async () => { | ||
const phone = '+10005551111'; | ||
|
||
try { | ||
await klass.execute('update', { email: payload.email, phone }); | ||
} catch (error) { | ||
console.log(error); | ||
expect(error.message).to.equal(`Field does not match requirements: [sub, undefined]`); | ||
} | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
const sinon = require('sinon'); | ||
|
||
import { expect } from 'chai'; | ||
|
||
import { httpWrapper as Http } from '@services/http'; | ||
import { User as user } from '@services/user'; | ||
|
||
describe('user', () => { | ||
const sandbox = sinon.createSandbox(); | ||
|
||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
|
||
describe('auth', () => { | ||
it('promise should resolve', async () => { | ||
let response; | ||
const payload = { mfa_token: 'foo' }; | ||
|
||
sandbox.stub(Http.prototype, 'post').resolves(payload); | ||
|
||
try { | ||
response = await user.auth('[email protected]', 'qux'); | ||
} catch (error) { | ||
console.log(error); | ||
} finally { | ||
expect(response).to.equal(payload.mfa_token); | ||
} | ||
}); | ||
|
||
it('promise should reject, but forward mfa_challenge', async () => { | ||
let response; | ||
const exception = { | ||
error: 'mfa_required', | ||
mfa_token: 'foo' | ||
} | ||
|
||
sandbox.stub(Http.prototype, 'post').rejects(exception); | ||
|
||
try { | ||
response = await user.auth('[email protected]', 'qux'); | ||
} catch (error) { | ||
console.log(error); | ||
} finally { | ||
expect(response).to.equal(exception.mfa_token); | ||
} | ||
}); | ||
|
||
it('promise should reject', async () => { | ||
const exception = { error: 'foo' }; | ||
|
||
sandbox.stub(Http.prototype, 'post').rejects(exception); | ||
|
||
try { | ||
await user.auth('[email protected]', 'qux'); | ||
} catch (error) { | ||
expect(error).to.deep.equal(exception); | ||
} | ||
}); | ||
}); | ||
|
||
describe('oauth', () => { | ||
it('promise should resolve', async () => { | ||
let request; | ||
sandbox.stub(Http.prototype, 'post').resolves(true); | ||
|
||
try { | ||
request = await user.oauth('foo', 'bar', 'baz'); | ||
} catch (error) { | ||
console.log(error); | ||
} finally { | ||
expect(request).to.be.true; | ||
} | ||
}); | ||
|
||
it('promise should reject', async () => { | ||
sandbox.stub(Http.prototype, 'post').rejects(false); | ||
|
||
try { | ||
await user.oauth('foo', 'bar', 'baz'); | ||
} catch (error) { | ||
expect(error).to.be.throw; | ||
} | ||
}); | ||
}); | ||
|
||
describe('oob', () => { | ||
it('promise should resolve', async () => { | ||
let request; | ||
sandbox.stub(Http.prototype, 'post').resolves({ oob_code: 'foo' }); | ||
|
||
try { | ||
request = await user.oob('bar'); | ||
} catch (error) { | ||
console.log(error); | ||
} finally { | ||
expect(request).to.equal('foo'); | ||
} | ||
}); | ||
|
||
it('promise should reject', async () => { | ||
let request; | ||
sandbox.stub(Http.prototype, 'post').rejects(false); | ||
|
||
try { | ||
request = await user.oob('bar'); | ||
} catch (error) { | ||
expect(request).to.be.throw; | ||
} | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.