Merge remote-tracking branch 'origin/master' into distinct-shouts-and-follows

This commit is contained in:
Grzegorz Leoniec 2019-03-04 17:37:23 +01:00
commit cbf697c031
No known key found for this signature in database
GPG Key ID: 3AA43686D4EB1377
4 changed files with 144 additions and 49 deletions

View File

@ -2,29 +2,21 @@ export default {
Mutation: {
CreateUser: async (resolve, root, args, context, info) => {
args.createdAt = (new Date()).toISOString()
args.disabled = false
args.deleted = false
const result = await resolve(root, args, context, info)
return result
},
CreatePost: async (resolve, root, args, context, info) => {
args.createdAt = (new Date()).toISOString()
args.disabled = false
args.deleted = false
const result = await resolve(root, args, context, info)
return result
},
CreateComment: async (resolve, root, args, context, info) => {
args.createdAt = (new Date()).toISOString()
args.disabled = false
args.deleted = false
const result = await resolve(root, args, context, info)
return result
},
CreateOrganization: async (resolve, root, args, context, info) => {
args.createdAt = (new Date()).toISOString()
args.disabled = false
args.deleted = false
const result = await resolve(root, args, context, info)
return result
},

View File

@ -1,4 +1,4 @@
import { rule, shield, allow } from 'graphql-shield'
import { rule, shield, allow, or } from 'graphql-shield'
/*
* TODO: implement
@ -7,14 +7,10 @@ import { rule, shield, allow } from 'graphql-shield'
const isAuthenticated = rule()(async (parent, args, ctx, info) => {
return ctx.user !== null
})
/*
const isAdmin = rule()(async (parent, args, ctx, info) => {
return ctx.user.role === 'ADMIN'
const isModerator = rule()(async (parent, args, { user }, info) => {
return user && (user.role === 'moderator' || user.role === 'admin')
})
const isModerator = rule()(async (parent, args, ctx, info) => {
return ctx.user.role === 'MODERATOR'
})
*/
const isAdmin = rule()(async (parent, args, { user }, info) => {
return user && (user.role === 'admin')
@ -24,13 +20,17 @@ const isMyOwn = rule({ cache: 'no_cache' })(async (parent, args, context, info)
return context.user.id === parent.id
})
const onlyEnabledContent = rule({ cache: 'strict' })(async (parent, args, ctx, info) => {
const { disabled, deleted } = args
return !(disabled || deleted)
})
// Permissions
const permissions = shield({
Query: {
statistics: allow,
currentUser: allow
// fruits: and(isAuthenticated, or(isAdmin, isModerator)),
// customers: and(isAuthenticated, isAdmin)
currentUser: allow,
Post: or(onlyEnabledContent, isModerator)
},
Mutation: {
CreatePost: isAuthenticated,
@ -47,7 +47,6 @@ const permissions = shield({
email: isMyOwn,
password: isMyOwn
}
// Post: isAuthenticated
})
export default permissions

View File

@ -1,38 +1,23 @@
const setDefaults = (args) => {
if (typeof args.deleted !== 'boolean') {
args.deleted = false
}
if (typeof args.disabled !== 'boolean') {
args.disabled = false
}
return args
}
export default {
Query: {
Post: async (resolve, root, args, context, info) => {
if (typeof args.deleted !== 'boolean') {
args.deleted = false
}
if (typeof args.disabled !== 'boolean') {
args.disabled = false
}
const result = await resolve(root, args, context, info)
return result
Post: (resolve, root, args, context, info) => {
return resolve(root, setDefaults(args), context, info)
},
Comment: async (resolve, root, args, context, info) => {
if (typeof args.deleted !== 'boolean') {
args.deleted = false
}
if (typeof args.disabled !== 'boolean') {
args.disabled = false
}
const result = await resolve(root, args, context, info)
return result
return resolve(root, setDefaults(args), context, info)
},
User: async (resolve, root, args, context, info) => {
if (typeof args.deleted !== 'boolean') {
args.deleted = false
}
if (typeof args.disabled !== 'boolean') {
args.disabled = false
}
// console.log('ROOT', root)
// console.log('ARGS', args)
// console.log('CONTEXT', context)
// console.log('info', info.fieldNodes[0].arguments)
const result = await resolve(root, args, context, info)
return result
return resolve(root, setDefaults(args), context, info)
}
}
}

View File

@ -0,0 +1,119 @@
import Factory from '../seed/factories'
import { host, login } from '../jest/helpers'
import { GraphQLClient } from 'graphql-request'
const factory = Factory()
let client
let query
let action
beforeEach(async () => {
await Promise.all([
factory.create('User', { role: 'user', email: 'user@example.org', password: '1234' }),
factory.create('User', { role: 'moderator', email: 'moderator@example.org', password: '1234' })
])
await factory.authenticateAs({ email: 'user@example.org', password: '1234' })
await Promise.all([
factory.create('Post', { title: 'Deleted post', deleted: true, disabled: false }),
factory.create('Post', { title: 'Disabled post', deleted: false, disabled: true }),
factory.create('Post', { title: 'Publicly visible post', deleted: false, disabled: false })
])
})
afterEach(async () => {
await factory.cleanDatabase()
})
describe('softDeleteMiddleware', () => {
describe('Post', () => {
action = () => {
return client.request(query)
}
beforeEach(() => {
query = '{ Post { title } }'
})
describe('as user', () => {
beforeEach(async () => {
const headers = await login({ email: 'user@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('hides deleted or disabled posts', async () => {
const expected = { Post: [{ title: 'Publicly visible post' }] }
await expect(action()).resolves.toEqual(expected)
})
})
describe('as moderator', () => {
beforeEach(async () => {
const headers = await login({ email: 'moderator@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('hides deleted or disabled posts', async () => {
const expected = { Post: [{ title: 'Publicly visible post' }] }
await expect(action()).resolves.toEqual(expected)
})
})
describe('filter (deleted: true)', () => {
beforeEach(() => {
query = '{ Post(deleted: true) { title } }'
})
describe('as user', () => {
beforeEach(async () => {
const headers = await login({ email: 'user@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('throws authorisation error', async () => {
await expect(action()).rejects.toThrow('Not Authorised!')
})
})
describe('as moderator', () => {
beforeEach(async () => {
const headers = await login({ email: 'moderator@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('shows deleted posts', async () => {
const expected = { Post: [{ title: 'Deleted post' }] }
await expect(action()).resolves.toEqual(expected)
})
})
})
describe('filter (disabled: true)', () => {
beforeEach(() => {
query = '{ Post(disabled: true) { title } }'
})
describe('as user', () => {
beforeEach(async () => {
const headers = await login({ email: 'user@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('throws authorisation error', async () => {
await expect(action()).rejects.toThrow('Not Authorised!')
})
})
describe('as moderator', () => {
beforeEach(async () => {
const headers = await login({ email: 'moderator@example.org', password: '1234' })
client = new GraphQLClient(host, { headers })
})
it('shows disabled posts', async () => {
const expected = { Post: [{ title: 'Disabled post' }] }
await expect(action()).resolves.toEqual(expected)
})
})
})
})
})