diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 78f833c23..93096acba 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -159,6 +159,7 @@ const permissions = shield( Badge: allow, PostsEmotionsCountByEmotion: allow, PostsEmotionsByCurrentUser: allow, + blockedUsers: isAuthenticated, }, Mutation: { '*': deny, diff --git a/backend/src/models/User.js b/backend/src/models/User.js index 5125c75ec..c952c0be6 100644 --- a/backend/src/models/User.js +++ b/backend/src/models/User.js @@ -53,7 +53,6 @@ module.exports = { relationship: 'BLOCKED', target: 'User', direction: 'out', - eager: true }, invitedBy: { type: 'relationship', relationship: 'INVITED', target: 'User', direction: 'in' }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index 393ae8281..b06f2d098 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -18,6 +18,23 @@ export default { } return neo4jgraphql(object, args, context, resolveInfo, false) }, + blockedUsers: async (object, args, context, resolveInfo) => { + try { + const userModel = instance.model('User') + let blockedUsers = instance + .query() + .match('user', userModel) + .where('user.id', context.user.id) + .relationship(userModel.relationships().get('blocked')) + .to('blocked', userModel) + .return('blocked') + blockedUsers = await blockedUsers.execute() + blockedUsers = blockedUsers.records.map(r => r.get('blocked').properties) + return blockedUsers + } catch (e) { + throw new UserInputError(e.message) + } + }, }, Mutation: { UpdateUser: async (object, args, context, resolveInfo) => { @@ -63,6 +80,18 @@ export default { const [{ email }] = result.records.map(r => r.get('e').properties) return email }, + isBlocked: async (parent, params, context, resolveInfo) => { + if (typeof parent.isBlocked !== 'undefined') return parent.isBlocked + const result = await instance.cypher( + ` + MATCH (u:User { id: $currentUser.id })-[:BLOCKED]->(b:User {id: $parent.id}) + RETURN COUNT(u) >= 1 as isBlocked + `, + { parent, currentUser: context.user }, + ) + const [record] = result.records + return record.get('isBlocked') + }, ...Resolver('User', { undefinedToNull: [ 'actorId', diff --git a/backend/src/schema/resolvers/users/blockedUsers.spec.js b/backend/src/schema/resolvers/users/blockedUsers.spec.js index 4a42f1c5c..c77ed76d3 100644 --- a/backend/src/schema/resolvers/users/blockedUsers.spec.js +++ b/backend/src/schema/resolvers/users/blockedUsers.spec.js @@ -1,12 +1,83 @@ import { createTestClient } from 'apollo-server-testing' import createServer from '../../../server' +import Factory from '../../../seed/factories' import { gql } from '../../../jest/helpers' +import { neode, getDriver } from '../../../bootstrap/neo4j' + +const driver = getDriver() +const factory = Factory() +const instance = neode() + +let currentUser +let blockedUser +let server + +beforeEach(() => { + ;({ server } = createServer({ + context: () => { + return { + user: currentUser, + driver, + } + }, + })) +}) + +afterEach(async () => { + await factory.cleanDatabase() +}) describe('blockedUsers', () => { - it.todo('throws permission error') + let blockedUserQuery + beforeEach(() => { + blockedUserQuery = gql` + query { + blockedUsers { + id + name + isBlocked + } + } + ` + }) - describe('authenticated', () => { - it.todo('returns a list of blocked users') + it('throws permission error', async () => { + const { query } = createTestClient(server) + const result = await query({ query: blockedUserQuery }) + expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + + describe('authenticated and given a blocked user', () => { + beforeEach(async () => { + currentUser = await instance.create('User', { + name: 'Current User', + id: 'u1', + }) + blockedUser = await instance.create('User', { + name: 'Blocked User', + id: 'u2', + }) + await currentUser.relateTo(blockedUser, 'blocked') + currentUser = await currentUser.toJson() + blockedUser = await blockedUser.toJson() + }) + + it('returns a list of blocked users', async () => { + const { query } = createTestClient(server) + await expect(query({ query: blockedUserQuery })).resolves.toEqual( + expect.objectContaining({ + data: { + blockedUsers: [ + { + name: 'Blocked User', + id: 'u2', + isBlocked: true, + }, + ], + }, + }), + ) + }) }) }) @@ -18,6 +89,7 @@ describe('block', () => { describe('given a to-be-blocked user', () => { it.todo('blocks a user') + it.todo('removes any `FOLLOW` relationship') describe('blocked user writes a post', () => { it.todo('disappears in the newsfeed of the current user') diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index 74be4b5a6..c0b8220f5 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -152,6 +152,8 @@ type Query { orderBy: [_UserOrdering] filter: _UserFilter ): [User] + + blockedUsers: [User] } type Mutation { @@ -172,5 +174,4 @@ type Mutation { block(id: ID!): User unblock(id: ID!): User - blockedUsers: [User] }