From 4d630b8d88cc19d52a7f176d9d4e7347e038b7df Mon Sep 17 00:00:00 2001 From: DaviMBDev Date: Sat, 25 Apr 2026 17:36:37 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20s=C3=B3=20o=20atendente=20v=C3=AA=20o?= =?UTF-8?q?=20chat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/application/chat.service.spec.ts | 20 +++++++++++++++++++ .../modules/chat/application/chat.service.ts | 4 ++-- .../chat/presentation/chat.gateway.spec.ts | 13 ++++++++++++ .../modules/chat/presentation/chat.gateway.ts | 2 +- package-lock.json | 6 ++++++ 5 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 package-lock.json diff --git a/backend/src/modules/chat/application/chat.service.spec.ts b/backend/src/modules/chat/application/chat.service.spec.ts index 90f6eb9..d9d082c 100644 --- a/backend/src/modules/chat/application/chat.service.spec.ts +++ b/backend/src/modules/chat/application/chat.service.spec.ts @@ -202,6 +202,16 @@ describe('ChatService', () => { expect(mockMessageRepository.create).toHaveBeenCalledTimes(1); }); + it('should throw ForbiddenException when SUPPORT tries to send message and is not a participant', async () => { + mockChatRepository.findById.mockResolvedValue(mockChat); + + await expect( + service.sendMessage(CHAT_ID, OUTSIDER_ID, UserRole.SUPPORT, 'Intruso suporte!'), + ).rejects.toThrow(ForbiddenException); + + expect(mockMessageRepository.create).not.toHaveBeenCalled(); + }); + it('should throw ForbiddenException when sender is not a participant', async () => { mockChatRepository.findById.mockResolvedValue(mockChat); @@ -266,6 +276,16 @@ describe('ChatService', () => { expect(result).toEqual(mockMessages); }); + it('should throw ForbiddenException when SUPPORT tries to view history and is not a participant', async () => { + mockChatRepository.findById.mockResolvedValue(mockChat); + + await expect( + service.getChatHistory(CHAT_ID, OUTSIDER_ID, UserRole.SUPPORT), + ).rejects.toThrow(ForbiddenException); + + expect(mockMessageRepository.findByChatId).not.toHaveBeenCalled(); + }); + it('should throw ForbiddenException when user is not a participant', async () => { mockChatRepository.findById.mockResolvedValue(mockChat); diff --git a/backend/src/modules/chat/application/chat.service.ts b/backend/src/modules/chat/application/chat.service.ts index c2f2a6f..406c883 100644 --- a/backend/src/modules/chat/application/chat.service.ts +++ b/backend/src/modules/chat/application/chat.service.ts @@ -53,7 +53,7 @@ export class ChatService { } // ADMINs podem enviar mensagem em qualquer chat - if (senderRole !== UserRole.ADMIN && senderRole !== UserRole.SUPPORT) { + if (senderRole !== UserRole.ADMIN) { if (chat.clientId !== senderId && chat.agentId !== senderId) { throw new ForbiddenException('You are not a participant of this chat'); } @@ -79,7 +79,7 @@ export class ChatService { } // ADMINs podem ver histórico de qualquer chat - if (userRole !== UserRole.ADMIN && userRole !== UserRole.SUPPORT) { + if (userRole !== UserRole.ADMIN) { if (chat.clientId !== userId && chat.agentId !== userId) { throw new ForbiddenException('You are not a participant of this chat'); } diff --git a/backend/src/modules/chat/presentation/chat.gateway.spec.ts b/backend/src/modules/chat/presentation/chat.gateway.spec.ts index 4b0e10c..32beb06 100644 --- a/backend/src/modules/chat/presentation/chat.gateway.spec.ts +++ b/backend/src/modules/chat/presentation/chat.gateway.spec.ts @@ -178,6 +178,19 @@ describe('ChatGateway', () => { }); }); + it('should emit error when non-participant support tries to join', async () => { + const client = createMockSocket(); + client.data.user = { id: OUTSIDER_ID, email: 'suporte@e.com', role: 'support' }; + mockChatService.isParticipant.mockResolvedValue(false); + + await gateway.handleEntrarChat({ chatId: CHAT_ID }, client); + + expect(client.join).not.toHaveBeenCalled(); + expect(client.emit).toHaveBeenCalledWith('erro', { + mensagem: 'Você não é participante deste chat', + }); + }); + it('should emit error when user is not authenticated', async () => { const client = createMockSocket(); // client.data.user is undefined diff --git a/backend/src/modules/chat/presentation/chat.gateway.ts b/backend/src/modules/chat/presentation/chat.gateway.ts index 472167d..da44ba3 100644 --- a/backend/src/modules/chat/presentation/chat.gateway.ts +++ b/backend/src/modules/chat/presentation/chat.gateway.ts @@ -87,7 +87,7 @@ export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect { user.id, ); - if (!isParticipant && user.role !== 'admin' && user.role !== 'support') { + if (!isParticipant && user.role !== 'admin') { client.emit('erro', { mensagem: 'Você não é participante deste chat', }); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6872ff4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "ProDesk-backend", + "lockfileVersion": 3, + "requires": true, + "packages": {} +}