Implement backend lookup with normalizeEmail

This commit is contained in:
roschaefer 2019-11-04 23:09:49 +01:00
parent 1d15176500
commit bcf06dff25
6 changed files with 70 additions and 32 deletions

View File

@ -101,6 +101,7 @@
"slug": "~1.1.0",
"trunc-html": "~1.1.2",
"uuid": "~3.3.3",
"validator": "^12.0.0",
"wait-on": "~3.3.0",
"xregexp": "^4.2.4"
},

View File

@ -1,34 +1,7 @@
import uuid from 'uuid/v4'
import bcrypt from 'bcryptjs'
import createPasswordReset from './passwordReset/createPasswordReset'
export async function createPasswordReset(options) {
const { driver, nonce, email, issuedAt = new Date() } = options
const session = driver.session()
let response = {}
try {
const cypher = `
MATCH (u:User)-[:PRIMARY_EMAIL]->(e:EmailAddress {email:$email})
CREATE(pr:PasswordReset {nonce: $nonce, issuedAt: datetime($issuedAt), usedAt: NULL})
MERGE (u)-[:REQUESTED]->(pr)
RETURN e, pr, u
`
const transactionRes = await session.run(cypher, {
issuedAt: issuedAt.toISOString(),
nonce,
email,
})
const records = transactionRes.records.map(record => {
const { email } = record.get('e').properties
const { nonce } = record.get('pr').properties
const { name } = record.get('u').properties
return { email, nonce, name }
})
response = records[0] || {}
} finally {
session.close()
}
return response
}
export default {
Mutation: {

View File

@ -1,7 +1,7 @@
import Factory from '../../seed/factories'
import { gql } from '../../jest/helpers'
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
import { createPasswordReset } from './passwordReset'
import { createPasswordReset } from './passwordReset/createPasswordReset'
import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing'
@ -109,10 +109,7 @@ describe('passwordReset', () => {
describe('resetPassword', () => {
const setup = async (options = {}) => {
const { email = 'user@example.org', issuedAt = new Date(), nonce = 'abcdef' } = options
const session = driver.session()
await createPasswordReset({ driver, email, issuedAt, nonce })
session.close()
}
const mutation = gql`

View File

@ -0,0 +1,31 @@
import { normalizeEmail } from 'validator'
export default async function createPasswordReset(options) {
const { driver, nonce, email, issuedAt = new Date() } = options
const normalizedEmail = normalizeEmail(email)
const session = driver.session()
let response = {}
try {
const cypher = `
MATCH (u:User)-[:PRIMARY_EMAIL]->(e:EmailAddress {email:$email})
CREATE(pr:PasswordReset {nonce: $nonce, issuedAt: datetime($issuedAt), usedAt: NULL})
MERGE (u)-[:REQUESTED]->(pr)
RETURN e, pr, u
`
const transactionRes = await session.run(cypher, {
issuedAt: issuedAt.toISOString(),
nonce,
email: normalizedEmail,
})
const records = transactionRes.records.map(record => {
const { email } = record.get('e').properties
const { nonce } = record.get('pr').properties
const { name } = record.get('u').properties
return { email, nonce, name }
})
response = records[0] || {}
} finally {
session.close()
}
return response
}

View File

@ -0,0 +1,31 @@
import createPasswordReset from './createPasswordReset'
describe('createPasswordReset', () => {
const issuedAt = new Date()
const nonce = 'abcdef'
describe('email lookup', () => {
let driver
let mockSession
beforeEach(() => {
mockSession = {
close() {},
run: jest.fn().mockReturnValue({
records: {
map: jest.fn(() => [])
}
})
}
driver = { session: () => mockSession }
})
it('lowercases email address', async () => {
const email = 'stRaNGeCaSiNG@ExAmplE.ORG'
await createPasswordReset({ driver, email, issuedAt, nonce })
expect(mockSession.run.mock.calls)
.toEqual([[expect.any(String), expect.objectContaining({
email: 'strangecasing@example.org'
})]])
})
})
})

View File

@ -8418,6 +8418,11 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
validator@^12.0.0:
version "12.0.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-12.0.0.tgz#fb33221f5320abe2422cda2f517dc3838064e813"
integrity sha512-r5zA1cQBEOgYlesRmSEwc9LkbfNLTtji+vWyaHzRZUxCTHdsX3bd+sdHfs5tGZ2W6ILGGsxWxCNwT/h3IY/3ng==
vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"