From b04e922afc0ad2ce64c260d05bb166bbe8b5e53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Thu, 14 Mar 2019 16:24:16 +0100 Subject: [PATCH 1/5] Disabled users are unauthenticated --- src/jwt/decode.js | 3 ++- src/resolvers/user_management.spec.js | 29 ++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/jwt/decode.js b/src/jwt/decode.js index 0ab1e4529..6abc06dc1 100644 --- a/src/jwt/decode.js +++ b/src/jwt/decode.js @@ -13,7 +13,7 @@ export default async (driver, authorizationHeader) => { const session = driver.session() const query = ` MATCH (user:User {id: {id} }) - RETURN user {.id, .slug, .name, .avatar, .email, .role} as user + RETURN user {.id, .slug, .name, .avatar, .email, .role, .disabled} LIMIT 1 ` const result = await session.run(query, { id }) @@ -22,6 +22,7 @@ export default async (driver, authorizationHeader) => { return record.get('user') }) if (!currentUser) return null + if (currentUser.disabled) return null return { token, ...currentUser diff --git a/src/resolvers/user_management.spec.js b/src/resolvers/user_management.spec.js index c4b09df37..6df1b1626 100644 --- a/src/resolvers/user_management.spec.js +++ b/src/resolvers/user_management.spec.js @@ -73,11 +73,30 @@ describe('isLoggedIn', () => { }) describe('and a corresponding user in the database', () => { - it('returns true', async () => { - // see the decoded token above - await factory.create('User', { id: 'u3' }) - await expect(client.request(query)).resolves.toEqual({ - isLoggedIn: true + describe('user is enabled', () => { + it('returns true', async () => { + // see the decoded token above + await factory.create('User', { id: 'u3' }) + await expect(client.request(query)).resolves.toEqual({ + isLoggedIn: true + }) + }) + }) + + describe('user is disabled', () => { + beforeEach(async () => { + const moderatorParams = { email: 'moderator@example.org', role: 'moderator', password: '1234' } + const asModerator = Factory() + await asModerator.create('User', moderatorParams) + await asModerator.authenticateAs(moderatorParams) + await factory.create('User', { id: 'u3' }) + await asModerator.mutate('mutation($id: ID!) { disable(id: $id) }', { id: 'u3' }) + }) + + it('returns false', async () => { + await expect(client.request(query)).resolves.toEqual({ + isLoggedIn: false + }) }) }) }) From b0ce023f49eb5c7c17d323ab7cec2c16a5e2d2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Thu, 14 Mar 2019 16:44:22 +0100 Subject: [PATCH 2/5] Create failing test @abdellani your turn :muscle: --- src/resolvers/user_management.spec.js | 29 ++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/resolvers/user_management.spec.js b/src/resolvers/user_management.spec.js index 6df1b1626..1c21adac1 100644 --- a/src/resolvers/user_management.spec.js +++ b/src/resolvers/user_management.spec.js @@ -26,6 +26,14 @@ const jennyRostocksHeaders = { 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoidXNlciIsImxvY2F0aW9uTmFtZSI6bnVsbCwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJhYm91dCI6bnVsbCwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9zYXNoYV9zaGVzdGFrb3YvMTI4LmpwZyIsImlkIjoidTMiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5vcmciLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTU1MDg0NjY4MCwiZXhwIjoxNjM3MjQ2NjgwLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.eZ_mVKas4Wzoc_JrQTEWXyRn7eY64cdIg4vqQ-F_7Jc' } +const disable = async (id) => { + const moderatorParams = { email: 'moderator@example.org', role: 'moderator', password: '1234' } + const asModerator = Factory() + await asModerator.create('User', moderatorParams) + await asModerator.authenticateAs(moderatorParams) + await asModerator.mutate('mutation($id: ID!) { disable(id: $id) }', { id }) +} + beforeEach(async () => { await factory.create('User', { avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/jimmuirhead/128.jpg', @@ -85,12 +93,8 @@ describe('isLoggedIn', () => { describe('user is disabled', () => { beforeEach(async () => { - const moderatorParams = { email: 'moderator@example.org', role: 'moderator', password: '1234' } - const asModerator = Factory() - await asModerator.create('User', moderatorParams) - await asModerator.authenticateAs(moderatorParams) await factory.create('User', { id: 'u3' }) - await asModerator.mutate('mutation($id: ID!) { disable(id: $id) }', { id: 'u3' }) + await disable('u3') }) it('returns false', async () => { @@ -187,6 +191,21 @@ describe('login', () => { }) }) + describe('valid email/password but user is disabled', () => { + it('responds with "Your account has been disabled."', async () => { + await disable('acb2d923-f3af-479e-9f00-61b12e864666') + await expect( + request( + host, + mutation({ + email: 'test@example.org', + password: '1234' + }) + ) + ).rejects.toThrow('Your account has been disabled.') + }) + }) + describe('with a valid email but incorrect password', () => { it('responds with "Incorrect email address or password."', async () => { await expect( From b4372dff36562c61b8c49da9751b809e9bd7ddbb Mon Sep 17 00:00:00 2001 From: abdellani Date: Fri, 15 Mar 2019 14:59:36 +0100 Subject: [PATCH 3/5] Show error message when a disabled user tries to authenticate --- src/resolvers/user_management.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/resolvers/user_management.js b/src/resolvers/user_management.js index 36865646f..ebb50f0b1 100644 --- a/src/resolvers/user_management.js +++ b/src/resolvers/user_management.js @@ -32,7 +32,7 @@ export default { const session = driver.session() const result = await session.run( 'MATCH (user:User {email: $userEmail}) ' + - 'RETURN user {.id, .slug, .name, .avatar, .email, .password, .role} as user LIMIT 1', + 'RETURN user {.id, .slug, .name, .avatar, .email, .password, .role, .disabled} as user LIMIT 1', { userEmail: email } @@ -45,11 +45,18 @@ export default { if ( currentUser && - (await bcrypt.compareSync(password, currentUser.password)) + (await bcrypt.compareSync(password, currentUser.password)) && + currentUser.disabled == false ) { delete currentUser.password return encode(currentUser) - } else { + } + else if (currentUser && + currentUser.disabled + ){ + throw new AuthenticationError('Your account has been disabled.') + } + else { throw new AuthenticationError('Incorrect email address or password.') } }, From b7cc18ee98e568cdf31ba41d3eafd21344a421db Mon Sep 17 00:00:00 2001 From: abdellani Date: Fri, 15 Mar 2019 18:33:07 +0100 Subject: [PATCH 4/5] Show error message when a disabled user tries to authenticate --- src/resolvers/user_management.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/resolvers/user_management.js b/src/resolvers/user_management.js index ebb50f0b1..c81d12c37 100644 --- a/src/resolvers/user_management.js +++ b/src/resolvers/user_management.js @@ -46,17 +46,15 @@ export default { if ( currentUser && (await bcrypt.compareSync(password, currentUser.password)) && - currentUser.disabled == false + !currentUser.disabled ) { delete currentUser.password return encode(currentUser) - } - else if (currentUser && + } else if (currentUser && currentUser.disabled - ){ + ) { throw new AuthenticationError('Your account has been disabled.') - } - else { + } else { throw new AuthenticationError('Incorrect email address or password.') } }, From eacb0a452e8fd6bc7f44e056a5373189376d6e84 Mon Sep 17 00:00:00 2001 From: abdellani Date: Fri, 15 Mar 2019 18:33:07 +0100 Subject: [PATCH 5/5] Show error message when a disabled user tries to authenticate --- src/resolvers/user_management.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/resolvers/user_management.js b/src/resolvers/user_management.js index ebb50f0b1..26dfb81db 100644 --- a/src/resolvers/user_management.js +++ b/src/resolvers/user_management.js @@ -46,17 +46,15 @@ export default { if ( currentUser && (await bcrypt.compareSync(password, currentUser.password)) && - currentUser.disabled == false + !currentUser.disabled ) { delete currentUser.password return encode(currentUser) - } - else if (currentUser && + } else if (currentUser && currentUser.disabled - ){ + ) { throw new AuthenticationError('Your account has been disabled.') - } - else { + } else { throw new AuthenticationError('Incorrect email address or password.') } },