Authorize and whitelist Notifications

This commit is contained in:
Robert Schäfer 2019-04-10 01:52:14 +02:00
parent 26caff5a9b
commit b63200ac8e
5 changed files with 103 additions and 9 deletions

View File

@ -7,6 +7,7 @@ import reports from './resolvers/reports.js'
import posts from './resolvers/posts.js'
import moderation from './resolvers/moderation.js'
import rewards from './resolvers/rewards.js'
import notifications from './resolvers/notifications'
export const typeDefs = fs
.readFileSync(
@ -17,13 +18,15 @@ export const typeDefs = fs
export const resolvers = {
Query: {
...statistics.Query,
...userManagement.Query
...userManagement.Query,
...notifications.Query
},
Mutation: {
...userManagement.Mutation,
...reports.Mutation,
...posts.Mutation,
...moderation.Mutation,
...rewards.Mutation
...rewards.Mutation,
...notifications.Mutation
}
}

View File

@ -20,6 +20,21 @@ const isMyOwn = rule({ cache: 'no_cache' })(async (parent, args, context, info)
return context.user.id === parent.id
})
const belongsToMe = rule({ cache: 'no_cache' })(async (_, args, context) => {
const { driver, user: { id: userId } } = context
const { id: notificationId } = args
const session = driver.session()
const result = await session.run(`
MATCH (u:User {id: $userId})<-[:NOTIFIED]-(n:Notification {id: $notificationId})
RETURN n
`, { userId, notificationId })
const [notification] = result.records.map((record) => {
return record.get('n')
})
session.close()
return Boolean(notification)
})
const onlyEnabledContent = rule({ cache: 'strict' })(async (parent, args, ctx, info) => {
const { disabled, deleted } = args
return !(disabled || deleted)
@ -50,6 +65,7 @@ const permissions = shield({
Post: or(onlyEnabledContent, isModerator)
},
Mutation: {
UpdateNotification: belongsToMe,
CreatePost: isAuthenticated,
UpdatePost: isAuthor,
DeletePost: isAuthor,

View File

@ -0,0 +1,14 @@
import { neo4jgraphql } from 'neo4j-graphql-js'
export default {
Query: {
Notification: (object, params, context, resolveInfo) => {
return neo4jgraphql(object, params, context, resolveInfo, false)
}
},
Mutation: {
UpdateNotification: (object, params, context, resolveInfo) => {
return neo4jgraphql(object, params, context, resolveInfo, false)
}
}
}

View File

@ -5,13 +5,14 @@ import { host, login } from '../jest/helpers'
const factory = Factory()
let client
let userParams = {
id: 'you',
email: 'test@example.org',
password: '1234'
}
beforeEach(async () => {
await factory.create('User', {
id: 'you',
email: 'test@example.org',
password: '1234'
})
await factory.create('User', userParams)
})
afterEach(async () => {
@ -118,3 +119,63 @@ describe('currentUser { notifications }', () => {
})
})
})
describe('UpdateNotification', () => {
const mutation = `mutation($id: ID!, $read: Boolean){
UpdateNotification(id: $id, read: $read) {
id read
}
}`
const variables = { id: 'to-be-updated', read: true }
describe('given a notifications', () => {
let headers
beforeEach(async () => {
const mentionedParams = {
id: 'mentioned-1',
email: 'mentioned@example.org',
password: '1234',
slug: 'mentioned'
}
await factory.create('User', mentionedParams)
await factory.create('Notification', { id: 'to-be-updated' })
await factory.authenticateAs(userParams)
await factory.create('Post', { id: 'p1' })
await Promise.all([
factory.relate('Notification', 'User', { from: 'to-be-updated', to: 'mentioned-1' }),
factory.relate('Notification', 'Post', { from: 'p1', to: 'to-be-updated' })
])
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
client = new GraphQLClient(host)
await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
})
})
describe('authenticated', () => {
beforeEach(async () => {
headers = await login({ email: 'test@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('throws authorization error', async () => {
await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
})
describe('and owner', () => {
beforeEach(async () => {
headers = await login({ email: 'mentioned@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('updates notification', async () => {
const expected = { UpdateNotification: { id: 'to-be-updated', read: true } }
await expect(client.request(mutation, variables)).resolves.toEqual(expected)
})
})
})
})
})

View File

@ -28,10 +28,10 @@ let schema = makeAugmentedSchema({
resolvers,
config: {
query: {
exclude: ['Statistics', 'LoggedInUser']
exclude: ['Notfication', 'Statistics', 'LoggedInUser']
},
mutation: {
exclude: ['Statistics', 'LoggedInUser']
exclude: ['Notfication', 'Statistics', 'LoggedInUser']
},
debug: debug
}