diff --git a/src/middleware/permissionsMiddleware.js b/src/middleware/permissionsMiddleware.js index ec2261c5a..8cf35c2a3 100644 --- a/src/middleware/permissionsMiddleware.js +++ b/src/middleware/permissionsMiddleware.js @@ -1,4 +1,4 @@ -import { rule, shield, allow, or } from 'graphql-shield' +import { rule, shield, allow, and, or } from 'graphql-shield' /* * TODO: implement @@ -41,6 +41,11 @@ const isAuthor = rule({ cache: 'no_cache' })(async (parent, args, { user, driver return authorId === user.id }) +const fromUserMatchesCurrentUser = rule({ cache: 'no_cache' })(async (parent, args, { user, driver }) => { + const { from: { id: fromId } } = args + return user.id === fromId +}) + // Permissions const permissions = shield({ Query: { @@ -57,8 +62,8 @@ const permissions = shield({ UpdateBadge: isAdmin, DeleteBadge: isAdmin, - AddPostDisabledBy: isModerator, - RemovePostDisabledBy: isModerator, + AddPostDisabledBy: and(isModerator, fromUserMatchesCurrentUser), + RemovePostDisabledBy: and(isModerator, fromUserMatchesCurrentUser), // addFruitToBasket: isAuthenticated // CreateUser: allow, }, diff --git a/src/resolvers/posts.spec.js b/src/resolvers/posts.spec.js index cbe836b21..515216f34 100644 --- a/src/resolvers/posts.spec.js +++ b/src/resolvers/posts.spec.js @@ -201,52 +201,22 @@ describe('DeletePost', () => { }) }) -describe('AddPostDisabledBy', () => { - const mutation = ` - mutation { - AddPostDisabledBy(from: { id: "u8" }, to: { id: "p9" }) { - from { - id - } - to { - id - } - } + + + +describe('disabledBy relation', () => { + const setup = async (params = {}) => { + let headers = {} + const { email, password } = params + if (email && password) { + await factory.create('User', params) + headers = await login({email, password}) } - ` - it('throws authorization error', async () => { - client = new GraphQLClient(host) - await expect(client.request(mutation)).rejects.toThrow('Not Authorised') - }) + client = new GraphQLClient(host, { headers }) + } - describe('authenticated', () => { - let headers - beforeEach(async () => { - await factory.create('User', { - email: 'someUser@example.org', - password: '1234' - }) - headers = await login({ email: 'someUser@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) - }) - - it('throws authorization error', async () => { - await expect(client.request(mutation)).rejects.toThrow('Not Authorised') - }) - - describe('as moderator', () => { - it.todo('throws authorization error') - - describe('current user matches provided user', () => { - it.todo('sets current user') - it.todo('updates .disabled on post') - }) - }) - }) -}) - -describe('RemovePostDisabledBy', () => { - const mutation = ` + describe('AddPostDisabledBy', () => { + const mutation = ` mutation { AddPostDisabledBy(from: { id: "u8" }, to: { id: "p9" }) { from { @@ -259,32 +229,98 @@ describe('RemovePostDisabledBy', () => { } ` - it('throws authorization error', async () => { - client = new GraphQLClient(host) - await expect(client.request(mutation)).rejects.toThrow('Not Authorised') - }) - - describe('authenticated', () => { - let headers - beforeEach(async () => { - await factory.create('User', { - email: 'someUser@example.org', - password: '1234' - }) - headers = await login({ email: 'someUser@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) - }) - it('throws authorization error', async () => { + await setup() await expect(client.request(mutation)).rejects.toThrow('Not Authorised') }) - describe('as moderator', () => { - it.todo('throws authorization error') + describe('authenticated', () => { + it('throws authorization error', async () => { + await setup({ + email: 'someUser@example.org', + password: '1234' + }) + await expect(client.request(mutation)).rejects.toThrow('Not Authorised') + }) - describe('current user matches provided user', () => { - it.todo('sets current user') - it.todo('updates .disabled on post') + describe('as moderator', () => { + it('throws authorization error', async () => { + await setup({ + email: 'attributedUserMismatch@example.org', + password: '1234', + role: 'moderator' + }) + await expect(client.request(mutation)).rejects.toThrow('Not Authorised') + }) + + describe('current user matches provided user', () => { + beforeEach(async () => { + await setup({ + id: 'u7', + email: 'moderator@example.org', + password: '1234', + role: 'moderator' + }) + }) + + it.todo('sets current user') + it.todo('updates .disabled on post') + }) + }) + }) + }) + + describe('RemovePostDisabledBy', () => { + const mutation = ` + mutation { + AddPostDisabledBy(from: { id: "u8" }, to: { id: "p9" }) { + from { + id + } + to { + id + } + } + } + ` + + it('throws authorization error', async () => { + await setup() + await expect(client.request(mutation)).rejects.toThrow('Not Authorised') + }) + + describe('authenticated', () => { + it('throws authorization error', async () => { + await setup({ + email: 'someUser@example.org', + password: '1234' + }) + await expect(client.request(mutation)).rejects.toThrow('Not Authorised') + }) + + describe('as moderator', () => { + it('throws authorization error', async () => { + await setup({ + role: 'moderator', + email: 'someUser@example.org', + password: '1234' + }) + await expect(client.request(mutation)).rejects.toThrow('Not Authorised') + }) + + describe('current user matches provided user', () => { + beforeEach(async () => { + await setup({ + id: 'u7', + role: 'moderator', + email: 'someUser@example.org', + password: '1234' + }) + }) + + it.todo('sets current user') + it.todo('updates .disabled on post') + }) }) }) })