diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 93096acba..bd5046331 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -10,7 +10,7 @@ const instance = neode() const isAuthenticated = rule({ cache: 'contextual', })(async (_parent, _args, ctx, _info) => { - return ctx.user != null + return !!(ctx && ctx.user && ctx.user.id) }) const isModerator = rule()(async (parent, args, { user }, info) => { @@ -196,6 +196,7 @@ const permissions = shield( resetPassword: allow, AddPostEmotions: isAuthenticated, RemovePostEmotions: isAuthenticated, + block: isAuthenticated, }, User: { email: isMyOwn, diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index b06f2d098..394f74e8e 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -8,16 +8,6 @@ const instance = neode() export default { Query: { - User: async (object, args, context, resolveInfo) => { - const { email } = args - if (email) { - const e = await instance.first('EmailAddress', { email }) - let user = e.get('belongsTo') - user = await user.toJson() - return [user.node] - } - return neo4jgraphql(object, args, context, resolveInfo, false) - }, blockedUsers: async (object, args, context, resolveInfo) => { try { const userModel = instance.model('User') @@ -35,8 +25,27 @@ export default { throw new UserInputError(e.message) } }, + User: async (object, args, context, resolveInfo) => { + const { email } = args + if (email) { + const e = await instance.first('EmailAddress', { email }) + let user = e.get('belongsTo') + user = await user.toJson() + return [user.node] + } + return neo4jgraphql(object, args, context, resolveInfo, false) + }, }, Mutation: { + block: async (object, args, context, resolveInfo) => { + if(context.user.id === args.id) return null + const [user, blockedUser] = await Promise.all([ + instance.find('User', context.user.id), + instance.find('User', args.id) + ]) + await user.relateTo(blockedUser, 'blocked') + return blockedUser.toJson() + }, UpdateUser: async (object, args, context, resolveInfo) => { args = await fileUpload(args, { file: 'avatarUpload', url: 'avatar' }) try { diff --git a/backend/src/schema/resolvers/users/blockedUsers.spec.js b/backend/src/schema/resolvers/users/blockedUsers.spec.js index c77ed76d3..826ea649d 100644 --- a/backend/src/schema/resolvers/users/blockedUsers.spec.js +++ b/backend/src/schema/resolvers/users/blockedUsers.spec.js @@ -13,11 +13,15 @@ let blockedUser let server beforeEach(() => { + currentUser = undefined ;({ server } = createServer({ context: () => { return { user: currentUser, driver, + cypherParams: { + currentUserId: currentUser ? currentUser.id : null, + }, } }, })) @@ -59,7 +63,6 @@ describe('blockedUsers', () => { }) await currentUser.relateTo(blockedUser, 'blocked') currentUser = await currentUser.toJson() - blockedUser = await blockedUser.toJson() }) it('returns a list of blocked users', async () => { @@ -82,14 +85,79 @@ describe('blockedUsers', () => { }) describe('block', () => { - it.todo('throws permission error') + let blockAction + + beforeEach(() => { + currentUser = undefined + blockAction = (variables) => { + const { mutate } = createTestClient(server) + const blockMutation = gql`mutation($id: ID!) { + block(id: $id) { + id + name + isBlocked + } + }` + return mutate({ mutation: blockMutation, variables }) + } + }) + + it('throws permission error', async () => { + const result = await blockAction({ id: 'u2' }) + expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + }) describe('authenticated', () => { - it.todo('throws argument error') + beforeEach(async () => { + currentUser = await instance.create('User', { + name: 'Current User', + id: 'u1', + }) + currentUser = await currentUser.toJson() + }) + + describe('block yourself', () => { + it('returns null', async () => { + await expect(blockAction({ id: 'u1' })) + .resolves.toEqual(expect.objectContaining({ data: { block: null } })) + }) + }) + + describe('block not existing user', () => { + it('returns null', async () => { + await expect(blockAction({ id: 'u2' })) + .resolves.toEqual(expect.objectContaining({ data: { block: null } })) + }) + }) describe('given a to-be-blocked user', () => { - it.todo('blocks a user') - it.todo('removes any `FOLLOW` relationship') + beforeEach(async () => { + blockedUser = await instance.create('User', { + name: 'Blocked User', + id: 'u2', + }) + }) + + it('blocks a user', async () => { + await expect(blockAction({ id: 'u2' })) + .resolves.toEqual(expect.objectContaining({ + data: { block: { id: 'u2', name: 'Blocked User', isBlocked: true} } + })) + }) + + it('unfollows the user', async () => { + const user = await instance.find('User', currentUser.id) + await user.relateTo(blockedUser, 'following') + const queryUser = gql`query { User(id: "u2") { id isBlocked followedByCurrentUser } }` + const { query } = createTestClient(server) + await expect(query({ query: queryUser })).resolves.toEqual(expect.objectContaining({ + data: { User: [{id: "u2", isBlocked: false, followedByCurrentUser: true }] } + })) + await blockAction({id: 'u2'}) + await expect(query({ query: queryUser })).resolves.toEqual(expect.objectContaining({ + data: { User: [{id: "u2", isBlocked: true, followedByCurrentUser: false }] } + })) + }) describe('blocked user writes a post', () => { it.todo('disappears in the newsfeed of the current user')