diff --git a/.changeset/proud-apples-jog.md b/.changeset/proud-apples-jog.md new file mode 100644 index 000000000000..7a4fcd511e49 --- /dev/null +++ b/.changeset/proud-apples-jog.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +test: add missing omnichannel contact-center tests diff --git a/apps/meteor/app/authorization/server/constant/permissions.ts b/apps/meteor/app/authorization/server/constant/permissions.ts new file mode 100644 index 000000000000..17bff428929f --- /dev/null +++ b/apps/meteor/app/authorization/server/constant/permissions.ts @@ -0,0 +1,219 @@ +// Note: +// 1.if we need to create a role that can only edit channel message, but not edit group message +// then we can define edit--message instead of edit-message +// 2. admin, moderator, and user roles should not be deleted as they are referenced in the code. +export const permissions = [ + { _id: 'access-permissions', roles: ['admin'] }, + { _id: 'access-setting-permissions', roles: ['admin'] }, + { _id: 'add-oauth-service', roles: ['admin'] }, + { _id: 'add-user-to-joined-room', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'add-user-to-any-c-room', roles: ['admin'] }, + { _id: 'add-user-to-any-p-room', roles: [] }, + { _id: 'api-bypass-rate-limit', roles: ['admin', 'bot', 'app'] }, + { _id: 'archive-room', roles: ['admin', 'owner'] }, + { _id: 'assign-admin-role', roles: ['admin'] }, + { _id: 'assign-roles', roles: ['admin'] }, + { _id: 'ban-user', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'bulk-register-user', roles: ['admin'] }, + { _id: 'change-livechat-room-visitor', roles: ['admin', 'livechat-manager', 'livechat-agent'] }, + { _id: 'create-c', roles: ['admin', 'user', 'bot', 'app'] }, + { _id: 'create-d', roles: ['admin', 'user', 'bot', 'app'] }, + { _id: 'create-p', roles: ['admin', 'user', 'bot', 'app'] }, + { _id: 'create-personal-access-tokens', roles: ['admin', 'user'] }, + { _id: 'create-user', roles: ['admin'] }, + { _id: 'clean-channel-history', roles: ['admin'] }, + { _id: 'delete-c', roles: ['admin', 'owner'] }, + { _id: 'delete-d', roles: ['admin'] }, + { _id: 'delete-message', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'delete-own-message', roles: ['admin', 'user'] }, + { _id: 'delete-p', roles: ['admin', 'owner'] }, + { _id: 'delete-user', roles: ['admin'] }, + { _id: 'edit-message', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'edit-other-user-active-status', roles: ['admin'] }, + { _id: 'edit-other-user-info', roles: ['admin'] }, + { _id: 'edit-other-user-password', roles: ['admin'] }, + { _id: 'edit-other-user-avatar', roles: ['admin'] }, + { _id: 'edit-other-user-e2ee', roles: ['admin'] }, + { _id: 'edit-other-user-totp', roles: ['admin'] }, + { _id: 'edit-privileged-setting', roles: ['admin'] }, + { _id: 'edit-room', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'edit-room-avatar', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'edit-room-retention-policy', roles: ['admin'] }, + { _id: 'force-delete-message', roles: ['admin', 'owner'] }, + { _id: 'join-without-join-code', roles: ['admin', 'bot', 'app'] }, + { _id: 'leave-c', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, + { _id: 'leave-p', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, + { _id: 'logout-other-user', roles: ['admin'] }, + { _id: 'manage-assets', roles: ['admin'] }, + { _id: 'manage-email-inbox', roles: ['admin'] }, + { _id: 'manage-emoji', roles: ['admin'] }, + { _id: 'manage-user-status', roles: ['admin'] }, + { _id: 'manage-outgoing-integrations', roles: ['admin'] }, + { _id: 'manage-incoming-integrations', roles: ['admin'] }, + { _id: 'manage-own-outgoing-integrations', roles: ['admin'] }, + { _id: 'manage-own-incoming-integrations', roles: ['admin'] }, + { _id: 'manage-oauth-apps', roles: ['admin'] }, + { _id: 'manage-selected-settings', roles: ['admin'] }, + { _id: 'mention-all', roles: ['admin', 'owner', 'moderator', 'user'] }, + { _id: 'mention-here', roles: ['admin', 'owner', 'moderator', 'user'] }, + { _id: 'mute-user', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'remove-user', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'run-import', roles: ['admin'] }, + { _id: 'run-migration', roles: ['admin'] }, + { _id: 'set-moderator', roles: ['admin', 'owner'] }, + { _id: 'set-owner', roles: ['admin', 'owner'] }, + { _id: 'send-many-messages', roles: ['admin', 'bot', 'app'] }, + { _id: 'set-leader', roles: ['admin', 'owner'] }, + { _id: 'unarchive-room', roles: ['admin'] }, + { _id: 'view-c-room', roles: ['admin', 'user', 'bot', 'app', 'anonymous'] }, + { _id: 'user-generate-access-token', roles: ['admin'] }, + { _id: 'view-d-room', roles: ['admin', 'user', 'bot', 'app', 'guest'] }, + { _id: 'view-full-other-user-info', roles: ['admin'] }, + { _id: 'view-history', roles: ['admin', 'user', 'anonymous'] }, + { _id: 'view-joined-room', roles: ['guest', 'bot', 'app', 'anonymous'] }, + { _id: 'view-join-code', roles: ['admin'] }, + { _id: 'view-logs', roles: ['admin'] }, + { _id: 'view-other-user-channels', roles: ['admin'] }, + { _id: 'view-p-room', roles: ['admin', 'user', 'anonymous', 'guest'] }, + { _id: 'view-privileged-setting', roles: ['admin'] }, + { _id: 'view-room-administration', roles: ['admin'] }, + { _id: 'view-statistics', roles: ['admin'] }, + { _id: 'view-user-administration', roles: ['admin'] }, + { _id: 'preview-c-room', roles: ['admin', 'user', 'anonymous'] }, + { _id: 'view-outside-room', roles: ['admin', 'owner', 'moderator', 'user'] }, + { _id: 'view-broadcast-member-list', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'call-management', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'create-invite-links', roles: ['admin', 'owner', 'moderator'] }, + { + _id: 'view-l-room', + roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], + }, + { _id: 'view-livechat-manager', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { + _id: 'view-omnichannel-contact-center', + roles: ['livechat-manager', 'livechat-agent', 'livechat-monitor', 'admin'], + }, + { _id: 'edit-omnichannel-contact', roles: ['livechat-manager', 'livechat-agent', 'admin'] }, + { _id: 'view-livechat-rooms', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { + _id: 'close-livechat-room', + roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], + }, + { _id: 'close-others-livechat-room', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { + _id: 'on-hold-livechat-room', + roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], + }, + { + _id: 'on-hold-others-livechat-room', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { _id: 'save-others-livechat-room-info', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { + _id: 'remove-closed-livechat-rooms', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { _id: 'view-livechat-analytics', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { + _id: 'view-livechat-queue', + roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], + }, + { _id: 'transfer-livechat-guest', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { _id: 'manage-livechat-managers', roles: ['livechat-manager', 'admin'] }, + { _id: 'manage-livechat-agents', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { + _id: 'manage-livechat-departments', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { _id: 'view-livechat-departments', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, + { + _id: 'add-livechat-department-agents', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { + _id: 'view-livechat-current-chats', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { + _id: 'view-livechat-real-time-monitoring', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { _id: 'view-livechat-triggers', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-customfields', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-installation', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-appearance', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-webhooks', roles: ['livechat-manager', 'admin'] }, + { + _id: 'view-livechat-business-hours', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { + _id: 'view-livechat-room-closed-same-department', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { + _id: 'view-livechat-room-closed-by-another-agent', + roles: ['livechat-manager', 'livechat-monitor', 'admin'], + }, + { + _id: 'view-livechat-room-customfields', + roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], + }, + { + _id: 'edit-livechat-room-customfields', + roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], + }, + { _id: 'send-omnichannel-chat-transcript', roles: ['livechat-manager', 'admin'] }, + { _id: 'mail-messages', roles: ['admin'] }, + { _id: 'toggle-room-e2e-encryption', roles: ['owner', 'admin'] }, + { _id: 'message-impersonate', roles: ['bot', 'app'] }, + { _id: 'create-team', roles: ['admin', 'user'] }, + { _id: 'delete-team', roles: ['admin', 'owner'] }, + { _id: 'convert-team', roles: ['admin', 'owner'] }, + { _id: 'edit-team', roles: ['admin', 'owner'] }, + { _id: 'add-team-member', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'edit-team-member', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'add-team-channel', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'edit-team-channel', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'remove-team-channel', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'view-all-team-channels', roles: ['admin', 'owner'] }, + { _id: 'view-all-teams', roles: ['admin'] }, + { _id: 'remove-closed-livechat-room', roles: ['livechat-manager', 'admin'] }, + { _id: 'remove-livechat-department', roles: ['livechat-manager', 'admin'] }, + + // VOIP Permissions + // allows to manage voip calls configuration + { _id: 'manage-voip-call-settings', roles: ['livechat-manager', 'admin'] }, + { _id: 'manage-voip-contact-center-settings', roles: ['livechat-manager', 'admin'] }, + // allows agent-extension association. + { _id: 'manage-agent-extension-association', roles: ['admin'] }, + { _id: 'view-agent-extension-association', roles: ['livechat-manager', 'admin', 'livechat-agent'] }, + // allows to receive a voip call + { _id: 'inbound-voip-calls', roles: ['livechat-agent'] }, + + { _id: 'remove-livechat-department', roles: ['livechat-manager', 'admin'] }, + { _id: 'manage-apps', roles: ['admin'] }, + { _id: 'post-readonly', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'set-readonly', roles: ['admin', 'owner'] }, + { _id: 'set-react-when-readonly', roles: ['admin', 'owner'] }, + { _id: 'manage-cloud', roles: ['admin'] }, + { _id: 'manage-sounds', roles: ['admin'] }, + { _id: 'access-mailer', roles: ['admin'] }, + { _id: 'pin-message', roles: ['owner', 'moderator', 'admin'] }, + { _id: 'mobile-upload-file', roles: ['user', 'admin'] }, + { _id: 'send-mail', roles: ['admin'] }, + { _id: 'view-federation-data', roles: ['admin'] }, + { _id: 'add-all-to-room', roles: ['admin'] }, + { _id: 'get-server-info', roles: ['admin'] }, + { _id: 'register-on-cloud', roles: ['admin'] }, + { _id: 'test-admin-options', roles: ['admin'] }, + { _id: 'sync-auth-services-users', roles: ['admin'] }, + { _id: 'restart-server', roles: ['admin'] }, + { _id: 'remove-slackbridge-links', roles: ['admin'] }, + { _id: 'view-import-operations', roles: ['admin'] }, + { _id: 'clear-oembed-cache', roles: ['admin'] }, + { _id: 'videoconf-ring-users', roles: ['admin', 'owner', 'moderator', 'user'] }, + { _id: 'view-moderation-console', roles: ['admin'] }, + { _id: 'manage-moderation-actions', roles: ['admin'] }, + { _id: 'bypass-time-limit-edit-and-delete', roles: ['bot', 'app'] }, +]; diff --git a/apps/meteor/app/authorization/server/functions/upsertPermissions.ts b/apps/meteor/app/authorization/server/functions/upsertPermissions.ts index 2236b113433d..d48de450ac4b 100644 --- a/apps/meteor/app/authorization/server/functions/upsertPermissions.ts +++ b/apps/meteor/app/authorization/server/functions/upsertPermissions.ts @@ -5,228 +5,9 @@ import { Permissions, Settings } from '@rocket.chat/models'; import { settings } from '../../../settings/server'; import { getSettingPermissionId, CONSTANTS } from '../../lib'; import { createOrUpdateProtectedRoleAsync } from '../../../../server/lib/roles/createOrUpdateProtectedRole'; +import { permissions } from '../constant/permissions'; export const upsertPermissions = async (): Promise => { - // Note: - // 1.if we need to create a role that can only edit channel message, but not edit group message - // then we can define edit--message instead of edit-message - // 2. admin, moderator, and user roles should not be deleted as they are referenced in the code. - const permissions = [ - { _id: 'access-permissions', roles: ['admin'] }, - { _id: 'access-setting-permissions', roles: ['admin'] }, - { _id: 'add-oauth-service', roles: ['admin'] }, - { _id: 'add-user-to-joined-room', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'add-user-to-any-c-room', roles: ['admin'] }, - { _id: 'add-user-to-any-p-room', roles: [] }, - { _id: 'api-bypass-rate-limit', roles: ['admin', 'bot', 'app'] }, - { _id: 'archive-room', roles: ['admin', 'owner'] }, - { _id: 'assign-admin-role', roles: ['admin'] }, - { _id: 'assign-roles', roles: ['admin'] }, - { _id: 'ban-user', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'bulk-register-user', roles: ['admin'] }, - { _id: 'change-livechat-room-visitor', roles: ['admin', 'livechat-manager', 'livechat-agent'] }, - { _id: 'create-c', roles: ['admin', 'user', 'bot', 'app'] }, - { _id: 'create-d', roles: ['admin', 'user', 'bot', 'app'] }, - { _id: 'create-p', roles: ['admin', 'user', 'bot', 'app'] }, - { _id: 'create-personal-access-tokens', roles: ['admin', 'user'] }, - { _id: 'create-user', roles: ['admin'] }, - { _id: 'clean-channel-history', roles: ['admin'] }, - { _id: 'delete-c', roles: ['admin', 'owner'] }, - { _id: 'delete-d', roles: ['admin'] }, - { _id: 'delete-message', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'delete-own-message', roles: ['admin', 'user'] }, - { _id: 'delete-p', roles: ['admin', 'owner'] }, - { _id: 'delete-user', roles: ['admin'] }, - { _id: 'edit-message', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'edit-other-user-active-status', roles: ['admin'] }, - { _id: 'edit-other-user-info', roles: ['admin'] }, - { _id: 'edit-other-user-password', roles: ['admin'] }, - { _id: 'edit-other-user-avatar', roles: ['admin'] }, - { _id: 'edit-other-user-e2ee', roles: ['admin'] }, - { _id: 'edit-other-user-totp', roles: ['admin'] }, - { _id: 'edit-privileged-setting', roles: ['admin'] }, - { _id: 'edit-room', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'edit-room-avatar', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'edit-room-retention-policy', roles: ['admin'] }, - { _id: 'force-delete-message', roles: ['admin', 'owner'] }, - { _id: 'join-without-join-code', roles: ['admin', 'bot', 'app'] }, - { _id: 'leave-c', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, - { _id: 'leave-p', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, - { _id: 'logout-other-user', roles: ['admin'] }, - { _id: 'manage-assets', roles: ['admin'] }, - { _id: 'manage-email-inbox', roles: ['admin'] }, - { _id: 'manage-emoji', roles: ['admin'] }, - { _id: 'manage-user-status', roles: ['admin'] }, - { _id: 'manage-outgoing-integrations', roles: ['admin'] }, - { _id: 'manage-incoming-integrations', roles: ['admin'] }, - { _id: 'manage-own-outgoing-integrations', roles: ['admin'] }, - { _id: 'manage-own-incoming-integrations', roles: ['admin'] }, - { _id: 'manage-oauth-apps', roles: ['admin'] }, - { _id: 'manage-selected-settings', roles: ['admin'] }, - { _id: 'mention-all', roles: ['admin', 'owner', 'moderator', 'user'] }, - { _id: 'mention-here', roles: ['admin', 'owner', 'moderator', 'user'] }, - { _id: 'mute-user', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'remove-user', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'run-import', roles: ['admin'] }, - { _id: 'run-migration', roles: ['admin'] }, - { _id: 'set-moderator', roles: ['admin', 'owner'] }, - { _id: 'set-owner', roles: ['admin', 'owner'] }, - { _id: 'send-many-messages', roles: ['admin', 'bot', 'app'] }, - { _id: 'set-leader', roles: ['admin', 'owner'] }, - { _id: 'unarchive-room', roles: ['admin'] }, - { _id: 'view-c-room', roles: ['admin', 'user', 'bot', 'app', 'anonymous'] }, - { _id: 'user-generate-access-token', roles: ['admin'] }, - { _id: 'view-d-room', roles: ['admin', 'user', 'bot', 'app', 'guest'] }, - { _id: 'view-full-other-user-info', roles: ['admin'] }, - { _id: 'view-history', roles: ['admin', 'user', 'anonymous'] }, - { _id: 'view-joined-room', roles: ['guest', 'bot', 'app', 'anonymous'] }, - { _id: 'view-join-code', roles: ['admin'] }, - { _id: 'view-logs', roles: ['admin'] }, - { _id: 'view-other-user-channels', roles: ['admin'] }, - { _id: 'view-p-room', roles: ['admin', 'user', 'anonymous', 'guest'] }, - { _id: 'view-privileged-setting', roles: ['admin'] }, - { _id: 'view-room-administration', roles: ['admin'] }, - { _id: 'view-statistics', roles: ['admin'] }, - { _id: 'view-user-administration', roles: ['admin'] }, - { _id: 'preview-c-room', roles: ['admin', 'user', 'anonymous'] }, - { _id: 'view-outside-room', roles: ['admin', 'owner', 'moderator', 'user'] }, - { _id: 'view-broadcast-member-list', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'call-management', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'create-invite-links', roles: ['admin', 'owner', 'moderator'] }, - { - _id: 'view-l-room', - roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], - }, - { _id: 'view-livechat-manager', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { - _id: 'view-omnichannel-contact-center', - roles: ['livechat-manager', 'livechat-agent', 'livechat-monitor', 'admin'], - }, - { _id: 'edit-omnichannel-contact', roles: ['livechat-manager', 'livechat-agent', 'admin'] }, - { _id: 'view-livechat-rooms', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { - _id: 'close-livechat-room', - roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], - }, - { _id: 'close-others-livechat-room', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { - _id: 'on-hold-livechat-room', - roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], - }, - { - _id: 'on-hold-others-livechat-room', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { _id: 'save-others-livechat-room-info', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { - _id: 'remove-closed-livechat-rooms', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { _id: 'view-livechat-analytics', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { - _id: 'view-livechat-queue', - roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], - }, - { _id: 'transfer-livechat-guest', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { _id: 'manage-livechat-managers', roles: ['livechat-manager', 'admin'] }, - { _id: 'manage-livechat-agents', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { - _id: 'manage-livechat-departments', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { _id: 'view-livechat-departments', roles: ['livechat-manager', 'livechat-monitor', 'admin'] }, - { - _id: 'add-livechat-department-agents', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { - _id: 'view-livechat-current-chats', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { - _id: 'view-livechat-real-time-monitoring', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { _id: 'view-livechat-triggers', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-customfields', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-installation', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-appearance', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-webhooks', roles: ['livechat-manager', 'admin'] }, - { - _id: 'view-livechat-business-hours', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { - _id: 'view-livechat-room-closed-same-department', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { - _id: 'view-livechat-room-closed-by-another-agent', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, - { - _id: 'view-livechat-room-customfields', - roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], - }, - { - _id: 'edit-livechat-room-customfields', - roles: ['livechat-manager', 'livechat-monitor', 'livechat-agent', 'admin'], - }, - { _id: 'send-omnichannel-chat-transcript', roles: ['livechat-manager', 'admin'] }, - { _id: 'mail-messages', roles: ['admin'] }, - { _id: 'toggle-room-e2e-encryption', roles: ['owner', 'admin'] }, - { _id: 'message-impersonate', roles: ['bot', 'app'] }, - { _id: 'create-team', roles: ['admin', 'user'] }, - { _id: 'delete-team', roles: ['admin', 'owner'] }, - { _id: 'convert-team', roles: ['admin', 'owner'] }, - { _id: 'edit-team', roles: ['admin', 'owner'] }, - { _id: 'add-team-member', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'edit-team-member', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'add-team-channel', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'edit-team-channel', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'remove-team-channel', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'view-all-team-channels', roles: ['admin', 'owner'] }, - { _id: 'view-all-teams', roles: ['admin'] }, - { _id: 'remove-closed-livechat-room', roles: ['livechat-manager', 'admin'] }, - { _id: 'remove-livechat-department', roles: ['livechat-manager', 'admin'] }, - - // VOIP Permissions - // allows to manage voip calls configuration - { _id: 'manage-voip-call-settings', roles: ['livechat-manager', 'admin'] }, - { _id: 'manage-voip-contact-center-settings', roles: ['livechat-manager', 'admin'] }, - // allows agent-extension association. - { _id: 'manage-agent-extension-association', roles: ['admin'] }, - { _id: 'view-agent-extension-association', roles: ['livechat-manager', 'admin', 'livechat-agent'] }, - // allows to receive a voip call - { _id: 'inbound-voip-calls', roles: ['livechat-agent'] }, - - { _id: 'remove-livechat-department', roles: ['livechat-manager', 'admin'] }, - { _id: 'manage-apps', roles: ['admin'] }, - { _id: 'post-readonly', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'set-readonly', roles: ['admin', 'owner'] }, - { _id: 'set-react-when-readonly', roles: ['admin', 'owner'] }, - { _id: 'manage-cloud', roles: ['admin'] }, - { _id: 'manage-sounds', roles: ['admin'] }, - { _id: 'access-mailer', roles: ['admin'] }, - { _id: 'pin-message', roles: ['owner', 'moderator', 'admin'] }, - { _id: 'mobile-upload-file', roles: ['user', 'admin'] }, - { _id: 'send-mail', roles: ['admin'] }, - { _id: 'view-federation-data', roles: ['admin'] }, - { _id: 'add-all-to-room', roles: ['admin'] }, - { _id: 'get-server-info', roles: ['admin'] }, - { _id: 'register-on-cloud', roles: ['admin'] }, - { _id: 'test-admin-options', roles: ['admin'] }, - { _id: 'sync-auth-services-users', roles: ['admin'] }, - { _id: 'restart-server', roles: ['admin'] }, - { _id: 'remove-slackbridge-links', roles: ['admin'] }, - { _id: 'view-import-operations', roles: ['admin'] }, - { _id: 'clear-oembed-cache', roles: ['admin'] }, - { _id: 'videoconf-ring-users', roles: ['admin', 'owner', 'moderator', 'user'] }, - { _id: 'view-moderation-console', roles: ['admin'] }, - { _id: 'manage-moderation-actions', roles: ['admin'] }, - { _id: 'bypass-time-limit-edit-and-delete', roles: ['bot', 'app'] }, - ]; - for await (const permission of permissions) { await Permissions.create(permission._id, permission.roles); } diff --git a/apps/meteor/tests/data/livechat/rooms.ts b/apps/meteor/tests/data/livechat/rooms.ts index 073fe711eecb..429246d0189a 100644 --- a/apps/meteor/tests/data/livechat/rooms.ts +++ b/apps/meteor/tests/data/livechat/rooms.ts @@ -137,13 +137,13 @@ export const createAgent = (overrideUsername?: string): Promise }); }); -export const createManager = (): Promise => +export const createManager = (overrideUsername?: string): Promise => new Promise((resolve, reject) => { request .post(api('livechat/users/manager')) .set(credentials) .send({ - username: adminUsername, + username: overrideUsername || adminUsername, }) .end((err: Error, res: DummyResponse) => { if (err) { diff --git a/apps/meteor/tests/data/livechat/visitor.ts b/apps/meteor/tests/data/livechat/visitor.ts new file mode 100644 index 000000000000..86c1043fb05d --- /dev/null +++ b/apps/meteor/tests/data/livechat/visitor.ts @@ -0,0 +1,9 @@ +import { ILivechatVisitor } from '@rocket.chat/core-typings'; +import { expect } from 'chai'; +import { api, credentials, request } from '../api-data'; + +export const getLivechatVisitorByToken = async (token: string): Promise => { + const response = await request.get(api(`livechat/visitor/${token}`)).set(credentials).expect(200); + expect(response.body).to.have.property('visitor'); + return response.body.visitor; +} diff --git a/apps/meteor/tests/data/permissions.helper.ts b/apps/meteor/tests/data/permissions.helper.ts index d57bb4112718..263ae919f9cb 100644 --- a/apps/meteor/tests/data/permissions.helper.ts +++ b/apps/meteor/tests/data/permissions.helper.ts @@ -1,6 +1,7 @@ import type { ISetting } from '@rocket.chat/core-typings'; import { IS_EE } from '../e2e/config/constants'; import { api, credentials, request } from './api-data'; +import { permissions } from '../../app/authorization/server/constant/permissions'; export const updatePermission = (permission:string, roles:string[]):Promise => new Promise((resolve,reject) => { @@ -63,3 +64,30 @@ export const removePermissions = async (perms: string[]) => { export const addPermissions = async (perms: { [key: string]: string[] }) => { await updateManyPermissions(perms); }; + +type Permission = typeof permissions[number]['_id'] + +export const removePermissionFromAllRoles = async (permission: Permission) => { + await updatePermission(permission, []); +}; + +export const restorePermissionToRoles = async (permission: Permission) => { + const defaultPermission = permissions.find((p) => p._id === permission); + if (!defaultPermission) { + throw new Error(`No default roles found for permission ${permission}`); + } + + const mutableDefaultRoles: string[] = defaultPermission.roles.map((r) => r); + + if (!IS_EE) { + const eeOnlyRoles = ['livechat-monitor']; + eeOnlyRoles.forEach((role) => { + const index = mutableDefaultRoles.indexOf(role); + if (index !== -1) { + mutableDefaultRoles.splice(index, 1); + } + }); + } + + await updatePermission(permission, mutableDefaultRoles); +} diff --git a/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts b/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts index 59283d0b9788..038d6b0193e5 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts @@ -25,9 +25,17 @@ import { getLivechatRoomInfo, sendMessage, startANewLivechatRoomAndTakeIt, + createManager, closeOmnichannelRoom, } from '../../../data/livechat/rooms'; -import { addPermissions, updateEEPermission, updatePermission, updateSetting } from '../../../data/permissions.helper'; +import { + restorePermissionToRoles, + addPermissions, + removePermissionFromAllRoles, + updateEEPermission, + updatePermission, + updateSetting, +} from '../../../data/permissions.helper'; import { createUser, login } from '../../../data/users.helper.js'; import { adminUsername, password } from '../../../data/user'; import { createDepartmentWithAnOnlineAgent } from '../../../data/livechat/department'; @@ -119,7 +127,7 @@ describe('LIVECHAT - rooms', function () { describe('livechat/rooms', () => { it('should return an "unauthorized error" when the user does not have the necessary permission', async () => { - await updatePermission('view-livechat-rooms', []); + await removePermissionFromAllRoles('view-livechat-rooms'); await request .get(api('livechat/rooms')) .set(credentials) @@ -129,9 +137,10 @@ describe('LIVECHAT - rooms', function () { expect(res.body).to.have.property('success', false); expect(res.body.error).to.be.equal('unauthorized'); }); + + await restorePermissionToRoles('view-livechat-rooms'); }); it('should return an error when the "agents" query parameter is not valid', async () => { - await updatePermission('view-livechat-rooms', ['admin']); await request .get(api('livechat/rooms?agents=invalid')) .set(credentials) @@ -428,11 +437,12 @@ describe('LIVECHAT - rooms', function () { describe('livechat/room.join', () => { it('should fail if user doesnt have view-l-room permission', async () => { - await updatePermission('view-l-room', []); + await removePermissionFromAllRoles('view-l-room'); await request.get(api('livechat/room.join')).set(credentials).query({ roomId: '123' }).send().expect(403); + + await restorePermissionToRoles('view-l-room'); }); it('should fail if no roomId is present on query params', async () => { - await updatePermission('view-l-room', ['admin', 'livechat-agent']); await request.get(api('livechat/room.join')).set(credentials).expect(400); }); it('should fail if room is present but invalid', async () => { @@ -448,11 +458,13 @@ describe('LIVECHAT - rooms', function () { describe('livechat/room.join', () => { it('should fail if user doesnt have view-l-room permission', async () => { - await updatePermission('view-l-room', []); + await removePermissionFromAllRoles('view-l-room'); + await request.get(api('livechat/room.join')).set(credentials).query({ roomId: '123' }).send().expect(403); + + await restorePermissionToRoles('view-l-room'); }); it('should fail if no roomId is present on query params', async () => { - await updatePermission('view-l-room', ['admin', 'livechat-agent']); await request.get(api('livechat/room.join')).set(credentials).expect(400); }); it('should fail if room is present but invalid', async () => { @@ -464,6 +476,23 @@ describe('LIVECHAT - rooms', function () { await request.get(api('livechat/room.join')).set(credentials).query({ roomId: room._id }).send().expect(200); }); + it('should allow managers to join a room which is already being served by an agent', async () => { + await updateSetting('Livechat_Routing_Method', 'Manual_Selection'); + // delay for 1 second to make sure the routing queue gets stopped + await sleep(1000); + + const { + room: { _id: roomId }, + } = await startANewLivechatRoomAndTakeIt(); + + const manager: IUser = await createUser(); + const managerCredentials = await login(manager.username, password); + await createManager(manager.username); + + await request.get(api('livechat/room.join')).set(managerCredentials).query({ roomId }).send().expect(200); + + await updateSetting('Livechat_Routing_Method', 'Auto_Selection'); + }); }); describe('livechat/room.close', () => { @@ -572,7 +601,7 @@ describe('LIVECHAT - rooms', function () { describe('livechat/room.forward', () => { it('should return an "unauthorized error" when the user does not have "view-l-room" permission', async () => { await updatePermission('transfer-livechat-guest', ['admin']); - await updatePermission('view-l-room', []); + await removePermissionFromAllRoles('view-l-room'); await request .post(api('livechat/room.forward')) @@ -589,7 +618,7 @@ describe('LIVECHAT - rooms', function () { }); it('should return an "unauthorized error" when the user does not have "transfer-livechat-guest" permission', async () => { - await updatePermission('transfer-livechat-guest', []); + await removePermissionFromAllRoles('transfer-livechat-guest'); await updatePermission('view-l-room', ['admin']); await request @@ -604,12 +633,12 @@ describe('LIVECHAT - rooms', function () { expect(res.body).to.have.property('success', false); expect(res.body.error).to.have.string('unauthorized'); }); + + await restorePermissionToRoles('transfer-livechat-guest'); + await restorePermissionToRoles('view-l-room'); }); it('should not be successful when no target (userId or departmentId) was specified', async () => { - await updatePermission('transfer-livechat-guest', ['admin']); - await updatePermission('view-l-room', ['admin', 'livechat-manager', 'livechat-agent']); - await request .post(api('livechat/room.forward')) .set(credentials) @@ -832,12 +861,13 @@ describe('LIVECHAT - rooms', function () { await request.get(api('livechat/test/messages')).set(credentials).expect('Content-Type', 'application/json').expect(400); }); it('should throw an error if user doesnt have permission view-l-room', async () => { - await updatePermission('view-l-room', []); + await removePermissionFromAllRoles('view-l-room'); await request.get(api('livechat/test/messages')).set(credentials).expect('Content-Type', 'application/json').expect(403); + + await restorePermissionToRoles('view-l-room'); }); it('should return the messages of the room', async () => { - await updatePermission('view-l-room', ['admin']); const visitor = await createVisitor(); const room = await createLivechatRoom(visitor.token); await sendMessage(room._id, 'Hello', visitor.token); @@ -1246,16 +1276,17 @@ describe('LIVECHAT - rooms', function () { describe('livechat/transfer.history/:rid', () => { it('should fail if user doesnt have "view-livechat-rooms" permission', async () => { - await updatePermission('view-livechat-rooms', []); + await removePermissionFromAllRoles('view-livechat-rooms'); const { body } = await request .get(api(`livechat/transfer.history/test`)) .set(credentials) .expect('Content-Type', 'application/json') .expect(403); expect(body).to.have.property('success', false); + + await restorePermissionToRoles('view-livechat-rooms'); }); it('should fail if room is not a valid room id', async () => { - await updatePermission('view-livechat-rooms', ['admin', 'livechat-manager']); const { body } = await request .get(api(`livechat/transfer.history/test`)) .set(credentials) diff --git a/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts b/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts index de8cdae6723b..ba0cd8b083d2 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts @@ -3,9 +3,10 @@ import { expect } from 'chai'; import type { ILivechatVisitor } from '@rocket.chat/core-typings'; import type { Response } from 'supertest'; +import faker from '@faker-js/faker'; import { getCredentials, api, request, credentials } from '../../../data/api-data'; -import { updatePermission, updateSetting } from '../../../data/permissions.helper'; +import { updatePermission, updateSetting, removePermissionFromAllRoles, restorePermissionToRoles } from '../../../data/permissions.helper'; import { makeAgentAvailable, createAgent, @@ -14,6 +15,10 @@ import { startANewLivechatRoomAndTakeIt, } from '../../../data/livechat/rooms'; import { createCustomField, deleteCustomField } from '../../../data/livechat/custom-fields'; +import { getRandomVisitorToken } from '../../../data/livechat/users'; +import { getLivechatVisitorByToken } from '../../../data/livechat/visitor'; +import { adminUsername } from '../../../data/user'; +import { IS_EE } from '../../../e2e/config/constants'; describe('LIVECHAT - visitors', function () { this.retries(0); @@ -783,4 +788,125 @@ describe('LIVECHAT - visitors', function () { expect(res.body.visitors[0]).to.have.property('visitorEmails'); }); }); + describe('omnichannel/contact', () => { + let contact: ILivechatVisitor; + it('should fail if user doesnt have view-l-room permission', async () => { + await removePermissionFromAllRoles('view-l-room'); + const res = await request.get(api(`omnichannel/contact?text=nel`)).set(credentials).send(); + expect(res.body).to.have.property('success', false); + + await restorePermissionToRoles('view-l-room'); + }); + it('should create a new contact', async () => { + const token = getRandomVisitorToken(); + const res = await request.post(api('omnichannel/contact')).set(credentials).send({ + name: faker.name.findName(), + token, + }); + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('contact'); + expect(res.body.contact).to.be.an('string'); + const contactId: string = res.body.contact; + + contact = await getLivechatVisitorByToken(token); + expect(contact._id).to.equal(contactId); + }); + it('should update an existing contact', async () => { + const name = faker.name.findName(); + const res = await request.post(api('omnichannel/contact')).set(credentials).send({ + name, + token: contact.token, + }); + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('contact'); + expect(res.body.contact).to.be.an('string'); + expect(res.body.contact).to.equal(contact._id); + + contact = await getLivechatVisitorByToken(contact.token); + expect(contact.name).to.equal(name); + }); + it('should change the contact name, email and phone', async () => { + const name = faker.name.findName(); + const email = faker.internet.email().toLowerCase(); + const phone = faker.phone.phoneNumber(); + const res = await request.post(api('omnichannel/contact')).set(credentials).send({ + name, + email, + phone, + token: contact.token, + }); + + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('contact'); + expect(res.body.contact).to.be.an('string'); + expect(res.body.contact).to.equal(contact._id); + + contact = await getLivechatVisitorByToken(contact.token); + expect(contact.name).to.equal(name); + expect(contact.visitorEmails).to.be.an('array'); + expect(contact.visitorEmails).to.have.lengthOf(1); + if (contact.visitorEmails?.[0]) { + expect(contact.visitorEmails[0].address).to.equal(email); + } + expect(contact.phone).to.be.an('array'); + expect(contact.phone).to.have.lengthOf(1); + if (contact.phone?.[0]) { + expect(contact.phone[0].phoneNumber).to.equal(phone); + } + }); + (IS_EE ? it : it.skip)('should change the contact manager', async () => { + const managerUsername = adminUsername; + + const res = await request + .post(api('omnichannel/contact')) + .set(credentials) + .send({ + contactManager: { + username: managerUsername, + }, + token: contact.token, + name: contact.name, + }); + + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('contact'); + expect(res.body.contact).to.be.an('string'); + expect(res.body.contact).to.equal(contact._id); + + contact = await getLivechatVisitorByToken(contact.token); + expect(contact.contactManager).to.be.an('object'); + expect(contact.contactManager).to.have.property('username', managerUsername); + }); + it('should change custom fields', async () => { + const cfName = faker.lorem.word(); + await createCustomField({ + searchable: true, + field: cfName, + label: cfName, + scope: 'visitor', + visibility: 'visible', + regexp: '', + }); + + const res = await request + .post(api('omnichannel/contact')) + .set(credentials) + .send({ + token: contact.token, + name: contact.name, + customFields: { + [cfName]: 'test', + }, + }); + + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('contact'); + expect(res.body.contact).to.be.an('string'); + expect(res.body.contact).to.equal(contact._id); + + contact = await getLivechatVisitorByToken(contact.token); + expect(contact).to.have.property('livechatData'); + expect(contact.livechatData).to.have.property(cfName, 'test'); + }); + }); });