feat: adds new endpoint to disable Contacts by id (#36589)
Co-authored-by: Kevin Aleman <11577696+KevLehman@users.noreply.github.com>pull/36776/head^2
parent
cad0688f63
commit
3e177dbd0b
@ -0,0 +1,9 @@ |
||||
--- |
||||
"@rocket.chat/meteor": minor |
||||
"@rocket.chat/i18n": minor |
||||
"@rocket.chat/model-typings": minor |
||||
"@rocket.chat/models": minor |
||||
"@rocket.chat/rest-typings": minor |
||||
--- |
||||
|
||||
Adds new endpoint to disable Livechat Contacts by its id, with a new permission `delete-livechat-contact`. |
||||
@ -0,0 +1,23 @@ |
||||
import type { ILivechatContact } from '@rocket.chat/core-typings'; |
||||
import { LivechatContacts, LivechatRooms } from '@rocket.chat/models'; |
||||
|
||||
import { settings } from '../../../../settings/server'; |
||||
import { removeGuest } from '../guests'; |
||||
|
||||
export async function disableContactById(contactId: string): Promise<void> { |
||||
const contact = await LivechatContacts.findOneEnabledById<Pick<ILivechatContact, '_id' | 'channels'>>(contactId); |
||||
if (!contact) { |
||||
throw new Error('error-contact-not-found'); |
||||
} |
||||
|
||||
// Checking if the contact has any open channel/room before removing its data.
|
||||
const contactOpenRooms = await LivechatRooms.checkContactOpenRooms(contactId); |
||||
if (contactOpenRooms && !settings.get<boolean>('Livechat_Allow_collect_and_store_HTTP_header_informations')) { |
||||
throw new Error('error-contact-has-open-rooms'); |
||||
} |
||||
|
||||
// Cleaning contact/visitor data;
|
||||
await Promise.all(contact.channels.map((channel) => removeGuest({ _id: channel.visitor.visitorId }))); |
||||
|
||||
await LivechatContacts.disableByContactId(contactId); |
||||
} |
||||
@ -0,0 +1,105 @@ |
||||
import { expect } from 'chai'; |
||||
import proxyquire from 'proxyquire'; |
||||
import sinon from 'sinon'; |
||||
|
||||
const modelsMock = { |
||||
LivechatContacts: { |
||||
findOneEnabledById: sinon.stub(), |
||||
disableByContactId: sinon.stub(), |
||||
}, |
||||
LivechatRooms: { |
||||
checkContactOpenRooms: sinon.stub(), |
||||
}, |
||||
}; |
||||
|
||||
const settingsMock = { |
||||
get: sinon.stub(), |
||||
}; |
||||
|
||||
const removeGuestMock = { removeGuest: sinon.stub() }; |
||||
|
||||
const { disableContactById } = proxyquire.noCallThru().load('../../../../../../app/livechat/server/lib/contacts/disableContact.ts', { |
||||
'@rocket.chat/models': modelsMock, |
||||
'../guests': removeGuestMock, |
||||
'../../../../settings/server': { settings: settingsMock }, |
||||
}); |
||||
|
||||
describe('disableContact', () => { |
||||
const contact = { |
||||
_id: 'contact-id', |
||||
channels: [ |
||||
{ |
||||
visitor: { |
||||
visitorId: 'visitor-id', |
||||
}, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
beforeEach(() => { |
||||
modelsMock.LivechatContacts.findOneEnabledById.reset(); |
||||
modelsMock.LivechatRooms.checkContactOpenRooms.reset(); |
||||
modelsMock.LivechatContacts.disableByContactId.reset(); |
||||
settingsMock.get.reset(); |
||||
removeGuestMock.removeGuest.reset(); |
||||
}); |
||||
|
||||
it('should disable the contact', async () => { |
||||
settingsMock.get.withArgs('Livechat_Allow_collect_and_store_HTTP_header_informations').returns(true); |
||||
modelsMock.LivechatContacts.findOneEnabledById.resolves(contact); |
||||
modelsMock.LivechatRooms.checkContactOpenRooms.resolves(null); |
||||
removeGuestMock.removeGuest.resolves(); |
||||
modelsMock.LivechatContacts.disableByContactId.resolves(); |
||||
|
||||
await disableContactById(contact._id); |
||||
|
||||
expect(modelsMock.LivechatContacts.findOneEnabledById.calledOnceWith(contact._id)).to.be.true; |
||||
expect(modelsMock.LivechatRooms.checkContactOpenRooms.calledOnceWith(contact._id)).to.be.true; |
||||
expect(removeGuestMock.removeGuest.calledOnceWith({ _id: 'visitor-id' })).to.be.true; |
||||
expect(modelsMock.LivechatContacts.disableByContactId.calledOnceWith(contact._id)).to.be.true; |
||||
}); |
||||
|
||||
it('should call removeGuest for each channel the contact has communicated from', async () => { |
||||
contact.channels.push({ visitor: { visitorId: 'visitor-id-2' } }); |
||||
|
||||
settingsMock.get.withArgs('Livechat_Allow_collect_and_store_HTTP_header_informations').returns(true); |
||||
modelsMock.LivechatContacts.findOneEnabledById.resolves(contact); |
||||
modelsMock.LivechatRooms.checkContactOpenRooms.resolves(null); |
||||
removeGuestMock.removeGuest.resolves(); |
||||
modelsMock.LivechatContacts.disableByContactId.resolves(); |
||||
|
||||
await disableContactById(contact._id); |
||||
|
||||
expect(modelsMock.LivechatContacts.findOneEnabledById.calledOnceWith(contact._id)).to.be.true; |
||||
expect(modelsMock.LivechatContacts.findOneEnabledById.calledOnceWith(contact._id)).to.be.true; |
||||
expect(modelsMock.LivechatRooms.checkContactOpenRooms.calledOnceWith(contact._id)).to.be.true; |
||||
expect(removeGuestMock.removeGuest.calledTwice).to.be.true; |
||||
expect(removeGuestMock.removeGuest.getCall(0).args[0]).to.deep.equal({ _id: 'visitor-id' }); |
||||
expect(removeGuestMock.removeGuest.getCall(1).args[0]).to.deep.equal({ _id: 'visitor-id-2' }); |
||||
expect(modelsMock.LivechatContacts.disableByContactId.calledOnceWith(contact._id)).to.be.true; |
||||
}); |
||||
|
||||
it('should throw error if contact is not found', async () => { |
||||
modelsMock.LivechatContacts.findOneEnabledById.resolves(null); |
||||
|
||||
await expect(disableContactById('nonexistent-contact-id')).to.be.rejectedWith('error-contact-not-found'); |
||||
|
||||
expect(modelsMock.LivechatContacts.findOneEnabledById.calledOnceWith('nonexistent-contact-id')).to.be.true; |
||||
expect(modelsMock.LivechatRooms.checkContactOpenRooms.notCalled).to.be.true; |
||||
expect(removeGuestMock.removeGuest.notCalled).to.be.true; |
||||
expect(modelsMock.LivechatContacts.disableByContactId.notCalled).to.be.true; |
||||
}); |
||||
|
||||
it('should throw error if contact has open rooms and GDPR is disabled', async () => { |
||||
settingsMock.get.withArgs('Livechat_Allow_collect_and_store_HTTP_header_informations').returns(false); |
||||
modelsMock.LivechatContacts.findOneEnabledById.resolves(contact); |
||||
modelsMock.LivechatRooms.checkContactOpenRooms.resolves({ _id: 'room-id' }); |
||||
modelsMock.LivechatContacts.disableByContactId.resolves(); |
||||
|
||||
await expect(disableContactById(contact._id)).to.be.rejectedWith('error-contact-has-open-rooms'); |
||||
|
||||
expect(modelsMock.LivechatRooms.checkContactOpenRooms.calledOnceWith(contact._id)).to.be.true; |
||||
expect(removeGuestMock.removeGuest.notCalled).to.be.true; |
||||
expect(modelsMock.LivechatContacts.disableByContactId.notCalled).to.be.true; |
||||
}); |
||||
}); |
||||
Loading…
Reference in new issue