Expose yet another bug in the authorization

Cannot read property id of null

CC @appinteractive
This commit is contained in:
Robert Schäfer 2019-02-20 00:38:48 +01:00
parent 9c4e599ff1
commit f1dd52f579
3 changed files with 99 additions and 54 deletions

View File

@ -6,6 +6,7 @@ import generateJwt from './jwt/generateToken'
import uuid from 'uuid/v4'
import { fixUrl } from './middleware/fixImageUrlsMiddleware'
import { AuthenticationError } from 'apollo-server'
import { neo4jgraphql } from 'neo4j-graphql-js'
export const typeDefs =
fs.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql'))
@ -161,6 +162,22 @@ export const resolvers = {
// TODO: output Report compatible object
return data
},
CreatePost: async (object, params, ctx, resolveInfo) => {
const result = await neo4jgraphql(object, params, ctx, resolveInfo, false)
const session = ctx.driver.session()
await session.run(
'MATCH (author:User {id: $userId}), (post:Post {id: $postId}) ' +
'MERGE (post)<-[:WROTE]-(author) ' +
'RETURN author', {
userId: ctx.user.id,
postId: result.id
})
session.close()
return result
}
}
}

View File

@ -1,7 +1,18 @@
import { request } from 'graphql-request'
import { create, cleanDatabase } from './seed/factories'
import jwt from 'jsonwebtoken'
import { testServerHost as host } from './jest/helpers'
import { testServerHost as host, authenticatedHeaders } from './jest/helpers'
import { GraphQLClient, request } from 'graphql-request'
beforeEach(async () => {
await create('user', {
email: 'test@example.org',
password: '1234'
})
})
afterEach(async () => {
await cleanDatabase()
})
describe('login', () => {
const mutation = (params) => {
@ -14,48 +25,80 @@ describe('login', () => {
}`
}
describe('given an existing user', () => {
beforeEach(async () => {
await create('user', {
email: 'test@example.org',
password: '1234'
describe('ask for a `token`', () => {
describe('with valid email/password combination', () => {
it('responds with a JWT token', async () => {
const data = await request(host, mutation({ email: 'test@example.org', password: '1234' }))
const { token } = data.login
jwt.verify(token, process.env.JWT_SECRET, (err, data) => {
expect(data.email).toEqual('test@example.org')
expect(err).toBeNull()
})
})
})
afterEach(async () => {
await cleanDatabase()
describe('with a valid email but incorrect password', () => {
it('responds with "Incorrect email address or password."', async () => {
try {
await request(host, mutation({ email: 'test@example.org', password: 'wrong' }))
} catch (error) {
expect(error.response.errors[0].message).toEqual('Incorrect email address or password.')
}
})
})
describe('asking for a `token`', () => {
describe('with valid email/password combination', () => {
it('responds with a JWT token', async () => {
const data = await request(host, mutation({ email: 'test@example.org', password: '1234' }))
const { token } = data.login
jwt.verify(token, process.env.JWT_SECRET, (err, data) => {
expect(data.email).toEqual('test@example.org')
expect(err).toBeNull()
})
})
})
describe('with a valid email but incorrect password', () => {
it('responds with "Incorrect email address or password."', async () => {
try {
await request(host, mutation({ email: 'test@example.org', password: 'wrong' }))
} catch (error) {
expect(error.response.errors[0].message).toEqual('Incorrect email address or password.')
}
})
})
describe('with a non-existing email', () => {
it('responds with "Incorrect email address or password."', async () => {
try {
await request(host, mutation({ email: 'non-existent@example.org', password: 'wrong' }))
} catch (error) {
expect(error.response.errors[0].message).toEqual('Incorrect email address or password.')
}
})
describe('with a non-existing email', () => {
it('responds with "Incorrect email address or password."', async () => {
try {
await request(host, mutation({ email: 'non-existent@example.org', password: 'wrong' }))
} catch (error) {
expect(error.response.errors[0].message).toEqual('Incorrect email address or password.')
}
})
})
})
})
describe('CreatePost', () => {
describe('unauthenticated', () => {
let client
it('throws authorization error', async () => {
client = new GraphQLClient(host)
await expect(client.request(`mutation {
CreatePost(
title: "I am a post",
content: "Some content"
) { slug }
}`)).rejects.toThrow('Not Authorised')
})
describe('authenticated', () => {
let headers
let response
beforeEach(async () => {
headers = await authenticatedHeaders({ email: 'test@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
response = await client.request(`mutation {
CreatePost(
title: "A title",
content: "Some content"
) { title, content }
}`, { headers })
})
it('creates a post', () => {
expect(response).toEqual({ CreatePost: { title: 'A title', content: 'Some content' } })
})
it('assigns the authenticated user as author', async () => {
const { User } = await client.request(`{
User(email:"test@example.org") {
contributions {
title
}
}
}`, { headers })
expect(User).toEqual([ { contributions: [ { title: 'A title' } ] } ])
})
})
})

View File

@ -10,21 +10,6 @@ export default {
UpdateUser: async (resolve, root, args, context, info) => {
const result = await resolve(root, args, context, info)
await createOrUpdateLocations(args.id, args.locationName, context.driver)
return result
},
CreatePost: async (resolve, root, args, context, info) => {
const result = await resolve(root, args, context, info)
const session = context.driver.session()
await session.run(
'MATCH (author:User {id: $userId}), (post:Post {id: $postId}) ' +
'MERGE (post)<-[:WROTE]-(author) ' +
'RETURN author', {
userId: context.user.id,
postId: result.id
})
session.close()
return result
}
}