mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
fix(backend): block/mute chat (#8364)
* no notification when blocked * no notifications for muted users * move tests from emssage to notification middleware * fix test * also dont update unreadRoomCount when user is muted --------- Co-authored-by: mahula <lenzmath@posteo.de>
This commit is contained in:
parent
b31a439c8b
commit
2d8fe8a941
@ -31,8 +31,10 @@ jest.mock('../helpers/isUserOnline', () => ({
|
||||
isUserOnline: () => isUserOnlineMock(),
|
||||
}))
|
||||
|
||||
const pubsubSpy = jest.spyOn(pubsub, 'publish')
|
||||
|
||||
let server, query, mutate, notifiedUser, authenticatedUser
|
||||
let publishSpy
|
||||
|
||||
const driver = getDriver()
|
||||
const neode = getNeode()
|
||||
const categoryIds = ['cat9']
|
||||
@ -65,7 +67,6 @@ const createCommentMutation = gql`
|
||||
beforeAll(async () => {
|
||||
await cleanDatabase()
|
||||
|
||||
publishSpy = jest.spyOn(pubsub, 'publish')
|
||||
const createServerResult = createServer({
|
||||
context: () => {
|
||||
return {
|
||||
@ -87,7 +88,6 @@ afterAll(async () => {
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
publishSpy.mockClear()
|
||||
notifiedUser = await Factory.build(
|
||||
'user',
|
||||
{
|
||||
@ -417,7 +417,7 @@ describe('notifications', () => {
|
||||
|
||||
it('publishes `NOTIFICATION_ADDED` to me', async () => {
|
||||
await createPostAction()
|
||||
expect(publishSpy).toHaveBeenCalledWith(
|
||||
expect(pubsubSpy).toHaveBeenCalledWith(
|
||||
'NOTIFICATION_ADDED',
|
||||
expect.objectContaining({
|
||||
notificationAdded: expect.objectContaining({
|
||||
@ -428,7 +428,7 @@ describe('notifications', () => {
|
||||
}),
|
||||
}),
|
||||
)
|
||||
expect(publishSpy).toHaveBeenCalledTimes(1)
|
||||
expect(pubsubSpy).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
describe('updates the post and mentions me again', () => {
|
||||
@ -578,7 +578,7 @@ describe('notifications', () => {
|
||||
|
||||
it('does not publish `NOTIFICATION_ADDED`', async () => {
|
||||
await createPostAction()
|
||||
expect(publishSpy).not.toHaveBeenCalled()
|
||||
expect(pubsubSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -722,7 +722,7 @@ describe('notifications', () => {
|
||||
|
||||
it('does not publish `NOTIFICATION_ADDED` to authenticated user', async () => {
|
||||
await createCommentOnPostAction()
|
||||
expect(publishSpy).toHaveBeenCalledWith(
|
||||
expect(pubsubSpy).toHaveBeenCalledWith(
|
||||
'NOTIFICATION_ADDED',
|
||||
expect.objectContaining({
|
||||
notificationAdded: expect.objectContaining({
|
||||
@ -733,14 +733,14 @@ describe('notifications', () => {
|
||||
}),
|
||||
}),
|
||||
)
|
||||
expect(publishSpy).toHaveBeenCalledTimes(1)
|
||||
expect(pubsubSpy).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('chat email notifications', () => {
|
||||
describe('chat notifications', () => {
|
||||
let chatSender
|
||||
let chatReceiver
|
||||
let roomId
|
||||
@ -779,7 +779,7 @@ describe('notifications', () => {
|
||||
})
|
||||
|
||||
describe('if the chatReceiver is online', () => {
|
||||
it('sends no email', async () => {
|
||||
it('publishes subscriptions but sends no email', async () => {
|
||||
isUserOnlineMock = jest.fn().mockReturnValue(true)
|
||||
|
||||
await mutate({
|
||||
@ -790,13 +790,32 @@ describe('notifications', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(pubsubSpy).toHaveBeenCalledWith('ROOM_COUNT_UPDATED', {
|
||||
roomCountUpdated: '1',
|
||||
userId: 'chatReceiver',
|
||||
})
|
||||
expect(pubsubSpy).toHaveBeenCalledWith('CHAT_MESSAGE_ADDED', {
|
||||
chatMessageAdded: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
content: 'Some nice message to chatReceiver',
|
||||
senderId: 'chatSender',
|
||||
username: 'chatSender',
|
||||
avatar: null,
|
||||
date: expect.any(String),
|
||||
saved: true,
|
||||
distributed: false,
|
||||
seen: false,
|
||||
}),
|
||||
userId: 'chatReceiver',
|
||||
})
|
||||
|
||||
expect(sendMailMock).not.toHaveBeenCalled()
|
||||
expect(chatMessageTemplateMock).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('if the chatReceiver is offline', () => {
|
||||
it('sends an email', async () => {
|
||||
it('publishes subscriptions and sends an email', async () => {
|
||||
isUserOnlineMock = jest.fn().mockReturnValue(false)
|
||||
|
||||
await mutate({
|
||||
@ -807,13 +826,32 @@ describe('notifications', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(pubsubSpy).toHaveBeenCalledWith('ROOM_COUNT_UPDATED', {
|
||||
roomCountUpdated: '1',
|
||||
userId: 'chatReceiver',
|
||||
})
|
||||
expect(pubsubSpy).toHaveBeenCalledWith('CHAT_MESSAGE_ADDED', {
|
||||
chatMessageAdded: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
content: 'Some nice message to chatReceiver',
|
||||
senderId: 'chatSender',
|
||||
username: 'chatSender',
|
||||
avatar: null,
|
||||
date: expect.any(String),
|
||||
saved: true,
|
||||
distributed: false,
|
||||
seen: false,
|
||||
}),
|
||||
userId: 'chatReceiver',
|
||||
})
|
||||
|
||||
expect(sendMailMock).toHaveBeenCalledTimes(1)
|
||||
expect(chatMessageTemplateMock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('if the chatReceiver has blocked chatSender', () => {
|
||||
it('sends no email', async () => {
|
||||
it('publishes no subscriptions and sends no email', async () => {
|
||||
isUserOnlineMock = jest.fn().mockReturnValue(false)
|
||||
await chatReceiver.relateTo(chatSender, 'blocked')
|
||||
|
||||
@ -825,13 +863,37 @@ describe('notifications', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(pubsubSpy).not.toHaveBeenCalled()
|
||||
expect(pubsubSpy).not.toHaveBeenCalled()
|
||||
|
||||
expect(sendMailMock).not.toHaveBeenCalled()
|
||||
expect(chatMessageTemplateMock).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('if the chatReceiver has muted chatSender', () => {
|
||||
it('publishes no subscriptions and sends no email', async () => {
|
||||
isUserOnlineMock = jest.fn().mockReturnValue(false)
|
||||
await chatReceiver.relateTo(chatSender, 'muted')
|
||||
|
||||
await mutate({
|
||||
mutation: createMessageMutation(),
|
||||
variables: {
|
||||
roomId,
|
||||
content: 'Some nice message to chatReceiver',
|
||||
},
|
||||
})
|
||||
|
||||
expect(pubsubSpy).not.toHaveBeenCalled()
|
||||
expect(pubsubSpy).not.toHaveBeenCalled()
|
||||
|
||||
expect(sendMailMock).not.toHaveBeenCalled()
|
||||
expect(chatMessageTemplateMock).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('if the chatReceiver has disabled `emailNotificationsChatMessage`', () => {
|
||||
it('sends no email', async () => {
|
||||
it('publishes subscriptions but sends no email', async () => {
|
||||
isUserOnlineMock = jest.fn().mockReturnValue(false)
|
||||
await chatReceiver.update({ emailNotificationsChatMessage: false })
|
||||
|
||||
@ -843,6 +905,25 @@ describe('notifications', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(pubsubSpy).toHaveBeenCalledWith('ROOM_COUNT_UPDATED', {
|
||||
roomCountUpdated: '1',
|
||||
userId: 'chatReceiver',
|
||||
})
|
||||
expect(pubsubSpy).toHaveBeenCalledWith('CHAT_MESSAGE_ADDED', {
|
||||
chatMessageAdded: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
content: 'Some nice message to chatReceiver',
|
||||
senderId: 'chatSender',
|
||||
username: 'chatSender',
|
||||
avatar: null,
|
||||
date: expect.any(String),
|
||||
saved: true,
|
||||
distributed: false,
|
||||
seen: false,
|
||||
}),
|
||||
userId: 'chatReceiver',
|
||||
})
|
||||
|
||||
expect(sendMailMock).not.toHaveBeenCalled()
|
||||
expect(chatMessageTemplateMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -7,7 +7,9 @@ import {
|
||||
import { isUserOnline } from '@middleware/helpers/isUserOnline'
|
||||
import { validateNotifyUsers } from '@middleware/validation/validationMiddleware'
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { pubsub, NOTIFICATION_ADDED } from '@src/server'
|
||||
import { getUnreadRoomsCount } from '@schema/resolvers/rooms'
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { pubsub, NOTIFICATION_ADDED, ROOM_COUNT_UPDATED, CHAT_MESSAGE_ADDED } from '@src/server'
|
||||
|
||||
import extractMentionedUsers from './mentions/extractMentionedUsers'
|
||||
|
||||
@ -436,7 +438,7 @@ const notifyUsersOfComment = async (label, commentId, reason, context) => {
|
||||
|
||||
const handleCreateMessage = async (resolve, root, args, context, resolveInfo) => {
|
||||
// Execute resolver
|
||||
const result = await resolve(root, args, context, resolveInfo)
|
||||
const message = await resolve(root, args, context, resolveInfo)
|
||||
|
||||
// Query Parameters
|
||||
const { roomId } = args
|
||||
@ -452,7 +454,7 @@ const handleCreateMessage = async (resolve, root, args, context, resolveInfo) =>
|
||||
MATCH (room)<-[:CHATS_IN]-(recipientUser:User)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||
WHERE NOT recipientUser.id = $currentUserId
|
||||
AND NOT (recipientUser)-[:BLOCKED]-(senderUser)
|
||||
AND NOT recipientUser.emailNotificationsChatMessage = false
|
||||
AND NOT (recipientUser)-[:MUTED]->(senderUser)
|
||||
RETURN senderUser {.*}, recipientUser {.*}, emailAddress {.email}
|
||||
`
|
||||
const txResponse = await transaction.run(messageRecipientCypher, {
|
||||
@ -471,13 +473,27 @@ const handleCreateMessage = async (resolve, root, args, context, resolveInfo) =>
|
||||
// Execute Query
|
||||
const { senderUser, recipientUser, email } = await messageRecipient
|
||||
|
||||
// Send EMail if we found a user(not blocked) and he is not considered online
|
||||
if (recipientUser && !isUserOnline(recipientUser)) {
|
||||
void sendMail(chatMessageTemplate({ email, variables: { senderUser, recipientUser } }))
|
||||
if (recipientUser) {
|
||||
// send subscriptions
|
||||
const roomCountUpdated = await getUnreadRoomsCount(recipientUser.id, session)
|
||||
|
||||
void pubsub.publish(ROOM_COUNT_UPDATED, {
|
||||
roomCountUpdated,
|
||||
userId: recipientUser.id,
|
||||
})
|
||||
void pubsub.publish(CHAT_MESSAGE_ADDED, {
|
||||
chatMessageAdded: message,
|
||||
userId: recipientUser.id,
|
||||
})
|
||||
|
||||
// Send EMail if we found a user(not blocked) and he is not considered online
|
||||
if (recipientUser.emailNotificationsChatMessage !== false && !isUserOnline(recipientUser)) {
|
||||
void sendMail(chatMessageTemplate({ email, variables: { senderUser, recipientUser } }))
|
||||
}
|
||||
}
|
||||
|
||||
// Return resolver result to client
|
||||
return result
|
||||
return message
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
|
||||
@ -9,13 +9,13 @@ import createServer, { pubsub } from '@src/server'
|
||||
const driver = getDriver()
|
||||
const neode = getNeode()
|
||||
|
||||
const pubsubSpy = jest.spyOn(pubsub, 'publish')
|
||||
|
||||
let query
|
||||
let mutate
|
||||
let authenticatedUser
|
||||
let chattingUser, otherChattingUser, notChattingUser
|
||||
|
||||
const pubsubSpy = jest.spyOn(pubsub, 'publish')
|
||||
|
||||
beforeAll(async () => {
|
||||
await cleanDatabase()
|
||||
|
||||
@ -118,7 +118,7 @@ describe('Message', () => {
|
||||
})
|
||||
|
||||
describe('user chats in room', () => {
|
||||
it('returns the message and publishes subscriptions', async () => {
|
||||
it('returns the message', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createMessageMutation(),
|
||||
@ -143,24 +143,6 @@ describe('Message', () => {
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(pubsubSpy).toBeCalledWith('ROOM_COUNT_UPDATED', {
|
||||
roomCountUpdated: '1',
|
||||
userId: 'other-chatting-user',
|
||||
})
|
||||
expect(pubsubSpy).toBeCalledWith('CHAT_MESSAGE_ADDED', {
|
||||
chatMessageAdded: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
content: 'Some nice message to other chatting user',
|
||||
senderId: 'chatting-user',
|
||||
username: 'Chatting User',
|
||||
avatar: expect.any(String),
|
||||
date: expect.any(String),
|
||||
saved: true,
|
||||
distributed: false,
|
||||
seen: false,
|
||||
}),
|
||||
userId: 'other-chatting-user',
|
||||
})
|
||||
})
|
||||
|
||||
describe('room is updated as well', () => {
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { withFilter } from 'graphql-subscriptions'
|
||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
|
||||
import { pubsub, ROOM_COUNT_UPDATED, CHAT_MESSAGE_ADDED } from '@src/server'
|
||||
import { pubsub, CHAT_MESSAGE_ADDED } from '@src/server'
|
||||
|
||||
import Resolver from './helpers/Resolver'
|
||||
import { getUnreadRoomsCount } from './rooms'
|
||||
|
||||
const setMessagesAsDistributed = async (undistributedMessagesIds, session) => {
|
||||
return session.writeTransaction(async (transaction) => {
|
||||
@ -111,22 +110,7 @@ export default {
|
||||
return message
|
||||
})
|
||||
try {
|
||||
const message = await writeTxResultPromise
|
||||
if (message) {
|
||||
const roomCountUpdated = await getUnreadRoomsCount(message.recipientId, session)
|
||||
|
||||
// send subscriptions
|
||||
void pubsub.publish(ROOM_COUNT_UPDATED, {
|
||||
roomCountUpdated,
|
||||
userId: message.recipientId,
|
||||
})
|
||||
void pubsub.publish(CHAT_MESSAGE_ADDED, {
|
||||
chatMessageAdded: message,
|
||||
userId: message.recipientId,
|
||||
})
|
||||
}
|
||||
|
||||
return message
|
||||
return await writeTxResultPromise
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
|
||||
@ -387,6 +387,34 @@ describe('Room', () => {
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('when chattingUser is blocked has 0 unread rooms', async () => {
|
||||
authenticatedUser = await otherChattingUser.toJson()
|
||||
await otherChattingUser.relateTo(chattingUser, 'blocked')
|
||||
await expect(
|
||||
query({
|
||||
query: unreadRoomsQuery(),
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
UnreadRooms: 0,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('when chattingUser is muted has 0 unread rooms', async () => {
|
||||
authenticatedUser = await otherChattingUser.toJson()
|
||||
await otherChattingUser.relateTo(chattingUser, 'muted')
|
||||
await expect(
|
||||
query({
|
||||
query: unreadRoomsQuery(),
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
UnreadRooms: 0,
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('as not chatting user', () => {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { withFilter } from 'graphql-subscriptions'
|
||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { pubsub, ROOM_COUNT_UPDATED } from '@src/server'
|
||||
|
||||
import Resolver from './helpers/Resolver'
|
||||
@ -8,8 +9,10 @@ import Resolver from './helpers/Resolver'
|
||||
export const getUnreadRoomsCount = async (userId, session) => {
|
||||
return session.readTransaction(async (transaction) => {
|
||||
const unreadRoomsCypher = `
|
||||
MATCH (:User { id: $userId })-[:CHATS_IN]->(room:Room)<-[:INSIDE]-(message:Message)<-[:CREATED]-(sender:User)
|
||||
MATCH (user:User { id: $userId })-[:CHATS_IN]->(room:Room)<-[:INSIDE]-(message:Message)<-[:CREATED]-(sender:User)
|
||||
WHERE NOT sender.id = $userId AND NOT message.seen
|
||||
AND NOT (user)-[:BLOCKED]->(sender)
|
||||
AND NOT (user)-[:MUTED]->(sender)
|
||||
RETURN toString(COUNT(DISTINCT room)) AS count
|
||||
`
|
||||
const unreadRoomsTxResponse = await transaction.run(unreadRoomsCypher, { userId })
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user