diff --git a/keyserver/src/creators/thread-creator.js b/keyserver/src/creators/thread-creator.js --- a/keyserver/src/creators/thread-creator.js +++ b/keyserver/src/creators/thread-creator.js @@ -195,7 +195,7 @@ validateMembers: { initialMemberIDs, ghostMemberIDs }, } = await promiseAll(checkPromises); - if (sourceMessage && isInvalidSidebarSource(sourceMessage.type)) { + if (sourceMessage && isInvalidSidebarSource(sourceMessage)) { throw new ServerError('invalid_parameters'); } diff --git a/keyserver/src/fetchers/message-fetchers.js b/keyserver/src/fetchers/message-fetchers.js --- a/keyserver/src/fetchers/message-fetchers.js +++ b/keyserver/src/fetchers/message-fetchers.js @@ -5,6 +5,7 @@ import { sortMessageInfoList, shimUnsupportedRawMessageInfos, + isInvalidSidebarSource, } from 'lib/shared/message-utils.js'; import { messageSpecs } from 'lib/shared/messages/message-specs.js'; import { getNotifCollapseKey } from 'lib/shared/notif-utils.js'; @@ -26,7 +27,6 @@ defaultMaxMessageAge, type FetchPinnedMessagesRequest, type FetchPinnedMessagesResult, - isMessageSidebarSourceReactionEditOrPin, type SearchMessagesResponse, } from 'lib/types/message-types.js'; import { defaultNumberPerThread } from 'lib/types/message-types.js'; @@ -745,7 +745,7 @@ for (const message of messages) { let { rawMessageInfo } = message; invariant( - !isMessageSidebarSourceReactionEditOrPin(rawMessageInfo), + !isInvalidSidebarSource(rawMessageInfo), 'SIDEBAR_SOURCE or TOGGLE_PIN should not point to a ' + 'SIDEBAR_SOURCE, REACTION, EDIT_MESSAGE or TOGGLE_PIN', ); @@ -890,7 +890,7 @@ >(); for (const message of parsedResults) { const { rawMessageInfo } = message; - if (isMessageSidebarSourceReactionEditOrPin(rawMessageInfo)) { + if (isInvalidSidebarSource(rawMessageInfo)) { continue; } invariant(rawMessageInfo.id, 'rawMessageInfo.id should not be null'); diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js --- a/lib/shared/message-utils.js +++ b/lib/shared/message-utils.js @@ -653,12 +653,14 @@ return `${localIDPrefix}${nextLocalID}`; } -function isInvalidSidebarSource(messageType: number): boolean { +function isInvalidSidebarSource( + message: RawMessageInfo | MessageInfo, +): boolean %checks { return ( - messageType === messageTypes.REACTION || - messageType === messageTypes.EDIT_MESSAGE || - messageType === messageTypes.SIDEBAR_SOURCE || - messageType === messageTypes.TOGGLE_PIN + message.type === messageTypes.REACTION || + message.type === messageTypes.EDIT_MESSAGE || + message.type === messageTypes.SIDEBAR_SOURCE || + message.type === messageTypes.TOGGLE_PIN ); } diff --git a/lib/shared/message-utils.test.js b/lib/shared/message-utils.test.js --- a/lib/shared/message-utils.test.js +++ b/lib/shared/message-utils.test.js @@ -2,22 +2,417 @@ import { isInvalidSidebarSource } from './message-utils.js'; import { messageTypes } from '../types/message-types-enum.js'; -import { values } from '../utils/objects.js'; +import type { RawSidebarSourceMessageInfo } from '../types/message-types.js'; +import type { RawAddMembersMessageInfo } from '../types/messages/add-members.js'; +import type { RawChangeRoleMessageInfo } from '../types/messages/change-role.js'; +import type { RawChangeSettingsMessageInfo } from '../types/messages/change-settings.js'; +import type { RawCreateEntryMessageInfo } from '../types/messages/create-entry.js'; +import type { RawCreateSidebarMessageInfo } from '../types/messages/create-sidebar.js'; +import type { RawCreateSubthreadMessageInfo } from '../types/messages/create-subthread.js'; +import type { RawCreateThreadMessageInfo } from '../types/messages/create-thread.js'; +import type { RawDeleteEntryMessageInfo } from '../types/messages/delete-entry.js'; +import type { RawEditEntryMessageInfo } from '../types/messages/edit-entry.js'; +import type { RawEditMessageInfo } from '../types/messages/edit.js'; +import type { RawImagesMessageInfo } from '../types/messages/images.js'; +import type { RawJoinThreadMessageInfo } from '../types/messages/join-thread.js'; +import type { RawLeaveThreadMessageInfo } from '../types/messages/leave-thread.js'; +import type { RawMediaMessageInfo } from '../types/messages/media.js'; +import type { RawReactionMessageInfo } from '../types/messages/reaction.js'; +import type { RawRemoveMembersMessageInfo } from '../types/messages/remove-members.js'; +import type { RawRestoreEntryMessageInfo } from '../types/messages/restore-entry.js'; +import type { RawTextMessageInfo } from '../types/messages/text.js'; +import type { RawTogglePinMessageInfo } from '../types/messages/toggle-pin.js'; +import type { RawUpdateRelationshipMessageInfo } from '../types/messages/update-relationship.js'; +import { threadTypes } from '../types/thread-types-enum.js'; describe('isInvalidSidebarSource', () => { - it('should return true for all message types except for the ones listed', () => { - values(messageTypes).forEach(messageType => { - const shouldBeInvalidSidebarSource = isInvalidSidebarSource(messageType); - if ( - messageType === messageTypes.REACTION || - messageType === messageTypes.EDIT_MESSAGE || - messageType === messageTypes.SIDEBAR_SOURCE || - messageType === messageTypes.TOGGLE_PIN - ) { - expect(shouldBeInvalidSidebarSource).toBe(true); - } else { - expect(shouldBeInvalidSidebarSource).toBe(false); - } - }); + it('should return false for RawTextMessageInfo', () => { + const textMessageInfo: RawTextMessageInfo = { + type: messageTypes.TEXT, + localID: 'local1', + threadID: '10001', + creatorID: '123', + time: 10000, + text: 'This is a text message', + id: '1', + }; + + const shouldBeInvalidSidebarSource = + isInvalidSidebarSource(textMessageInfo); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawCreateThreadMessageInfo', () => { + const createThreadMessageInfo: RawCreateThreadMessageInfo = { + type: 1, + threadID: '10001', + creatorID: '123', + time: 10000, + initialThreadState: { + type: threadTypes.COMMUNITY_ROOT, + name: 'Random Thread', + parentThreadID: '10000', + color: '#FFFFFF', + memberIDs: ['1', '2', '3'], + }, + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + createThreadMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawAddMembersMessageInfo', () => { + const addMembersMessageInfo: RawAddMembersMessageInfo = { + type: messageTypes.ADD_MEMBERS, + threadID: '10001', + creatorID: '123', + time: 10000, + addedUserIDs: ['4', '5'], + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + addMembersMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawCreateSubthreadMessageInfo', () => { + const createSubthreadMessageInfo: RawCreateSubthreadMessageInfo = { + type: messageTypes.CREATE_SUB_THREAD, + threadID: '10001', + creatorID: '123', + time: 10000, + childThreadID: '10002', + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + createSubthreadMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawChangeSettingsMessageInfo', () => { + const changeSettingsMessageInfo: RawChangeSettingsMessageInfo = { + type: messageTypes.CHANGE_SETTINGS, + threadID: '10000', + creatorID: '123', + time: 10000, + field: 'color', + value: '#FFFFFF', + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + changeSettingsMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawRemoveMembersMessageInfo', () => { + const removeMembersMessageInfo: RawRemoveMembersMessageInfo = { + type: messageTypes.REMOVE_MEMBERS, + threadID: '10000', + creatorID: '123', + time: 10000, + removedUserIDs: ['1', '2', '3'], + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + removeMembersMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawChangeRoleMessageInfo', () => { + const changeRoleMessageinfo: RawChangeRoleMessageInfo = { + type: messageTypes.CHANGE_ROLE, + threadID: '10000', + creatorID: '123', + time: 10000, + userIDs: ['1', '2', '3'], + newRole: '101', + roleName: 'Moderators', + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + changeRoleMessageinfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawLeaveThreadMessageInfo', () => { + const leaveThreadMessageInfo: RawLeaveThreadMessageInfo = { + type: messageTypes.LEAVE_THREAD, + threadID: '10000', + creatorID: '123', + time: 10000, + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + leaveThreadMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawJoinThreadMessageInfo', () => { + const joinThreadMessageInfo: RawJoinThreadMessageInfo = { + type: messageTypes.JOIN_THREAD, + threadID: '10000', + creatorID: '123', + time: 10000, + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + joinThreadMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawCreateEntryMessageInfo', () => { + const createEntryMessageInfo: RawCreateEntryMessageInfo = { + type: messageTypes.CREATE_ENTRY, + threadID: '10000', + creatorID: '123', + time: 10000, + entryID: '001', + date: '2018-01-01', + text: 'This is a calendar entry', + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + createEntryMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawEditEntryMessageInfo', () => { + const editEntryMessageInfo: RawEditEntryMessageInfo = { + type: messageTypes.EDIT_ENTRY, + threadID: '10000', + creatorID: '123', + time: 10000, + entryID: '001', + date: '2018-01-01', + text: 'This is an edited calendar entry', + id: '1', + }; + + const shouldBeInvalidSidebarSource = + isInvalidSidebarSource(editEntryMessageInfo); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawDeleteEntryMessageInfo', () => { + const deleteEntryMessageInfo: RawDeleteEntryMessageInfo = { + type: messageTypes.DELETE_ENTRY, + threadID: '10000', + creatorID: '123', + time: 10000, + entryID: '001', + date: '2018-01-01', + text: 'This is a deleted calendar entry', + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + deleteEntryMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawRestoreEntryMessageInfo', () => { + const restoreEntryMessageInfo: RawRestoreEntryMessageInfo = { + type: messageTypes.RESTORE_ENTRY, + threadID: '10000', + creatorID: '123', + time: 10000, + entryID: '001', + date: '2018-01-01', + text: 'This is a restored calendar entry', + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + restoreEntryMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawUpdateRelationshipMessageInfo', () => { + const updateRelationshipMessageInfo: RawUpdateRelationshipMessageInfo = { + type: messageTypes.UPDATE_RELATIONSHIP, + threadID: '10000', + creatorID: '123', + targetID: '456', + time: 10000, + operation: 'request_sent', + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + updateRelationshipMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawImagesMessageInfo', () => { + const imageMessageInfo: RawImagesMessageInfo = { + type: messageTypes.IMAGES, + localID: 'local1', + threadID: '10001', + creatorID: '123', + time: 10000, + media: [ + { + id: '1', + uri: 'https://example.com/image1.jpg', + type: 'photo', + dimensions: { + height: 100, + width: 100, + }, + thumbHash: '1234567890', + }, + ], + id: '1', + }; + + const shouldBeInvalidSidebarSource = + isInvalidSidebarSource(imageMessageInfo); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return false for RawMediaMessageInfo', () => { + const mediaMessageInfo: RawMediaMessageInfo = { + type: messageTypes.MULTIMEDIA, + localID: 'local1', + threadID: '10001', + creatorID: '123', + time: 10000, + media: [ + { + id: '1', + uri: 'https://example.com/image1.jpg', + type: 'photo', + dimensions: { + height: 100, + width: 100, + }, + thumbHash: '1234567890', + }, + ], + id: '1', + }; + + const shouldBeInvalidSidebarSource = + isInvalidSidebarSource(mediaMessageInfo); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return true for RawSidebarSourceMessageInfo', () => { + const sidebarSourceMessageInfo: RawSidebarSourceMessageInfo = { + type: messageTypes.SIDEBAR_SOURCE, + threadID: '10000', + creatorID: '123', + time: 10000, + sourceMessage: { + type: messageTypes.TEXT, + localID: 'local1', + threadID: '10001', + creatorID: '123', + time: 10000, + text: 'This is a text message', + id: '1', + }, + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + sidebarSourceMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(true); + }); + + it('should return false for RawCreateSidebarMessageInfo', () => { + const createSidebarMessageInfo: RawCreateSidebarMessageInfo = { + type: messageTypes.CREATE_SIDEBAR, + threadID: '10000', + creatorID: '123', + time: 10000, + sourceMessageAuthorID: '123', + initialThreadState: { + name: 'Random Thread', + parentThreadID: '10000', + color: '#FFFFFF', + memberIDs: ['1', '2', '3'], + }, + id: '1', + }; + + const shouldBeInvalidSidebarSource = isInvalidSidebarSource( + createSidebarMessageInfo, + ); + expect(shouldBeInvalidSidebarSource).toBe(false); + }); + + it('should return true for RawReactionMessageInfo', () => { + const reactionMessageInfo: RawReactionMessageInfo = { + type: messageTypes.REACTION, + localID: 'local1', + threadID: '10001', + creatorID: '123', + time: 10000, + targetMessageID: '1', + reaction: 'like', + action: 'add_reaction', + id: '1', + }; + + const shouldBeInvalidSidebarSource = + isInvalidSidebarSource(reactionMessageInfo); + expect(shouldBeInvalidSidebarSource).toBe(true); + }); + + it('should return true for RawEditMessageInfo', () => { + const editMessageInfo: RawEditMessageInfo = { + type: messageTypes.EDIT_MESSAGE, + threadID: '10000', + creatorID: '123', + time: 10000, + targetMessageID: '1', + text: 'This is an edited message', + id: '1', + }; + + const shouldBeInvalidSidebarSource = + isInvalidSidebarSource(editMessageInfo); + expect(shouldBeInvalidSidebarSource).toBe(true); + }); + + it('should return true for RawTogglePinMessageInfo', () => { + const togglePinMessageInfo: RawTogglePinMessageInfo = { + type: messageTypes.TOGGLE_PIN, + threadID: '10000', + targetMessageID: '1', + action: 'pin', + pinnedContent: 'a message', + creatorID: '123', + time: 10000, + id: '1', + }; + + const shouldBeInvalidSidebarSource = + isInvalidSidebarSource(togglePinMessageInfo); + expect(shouldBeInvalidSidebarSource).toBe(true); }); }); diff --git a/lib/shared/messages/sidebar-source-message-spec.js b/lib/shared/messages/sidebar-source-message-spec.js --- a/lib/shared/messages/sidebar-source-message-spec.js +++ b/lib/shared/messages/sidebar-source-message-spec.js @@ -15,12 +15,12 @@ type SidebarSourceMessageData, type SidebarSourceMessageInfo, type ClientDBMessageInfo, - isMessageSidebarSourceReactionEditOrPin, rawSidebarSourceMessageInfoValidator, } from '../../types/message-types.js'; import type { RawUnsupportedMessageInfo } from '../../types/messages/unsupported.js'; import type { NotifTexts } from '../../types/notif-types.js'; import type { RelativeUserInfo } from '../../types/user-types.js'; +import { isInvalidSidebarSource } from '../message-utils.js'; export const sidebarSourceMessageSpec: MessageSpec< SidebarSourceMessageData, @@ -106,7 +106,7 @@ rawMessageInfo.sourceMessage, ); invariant( - sourceMessage && !isMessageSidebarSourceReactionEditOrPin(sourceMessage), + sourceMessage && !isInvalidSidebarSource(sourceMessage), 'Sidebars can not be created from SIDEBAR SOURCE, REACTION, EDIT OR PIN MESSAGE', ); diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -1265,7 +1265,7 @@ if ( !messageInfo.id || threadInfo.sourceMessageID === messageInfo.id || - isInvalidSidebarSource(messageInfo.type) + isInvalidSidebarSource(messageInfo) ) { return false; } diff --git a/lib/types/message-types.js b/lib/types/message-types.js --- a/lib/types/message-types.js +++ b/lib/types/message-types.js @@ -181,17 +181,6 @@ return messageData.localID; } -export function isMessageSidebarSourceReactionEditOrPin( - message: RawMessageInfo | MessageInfo, -): boolean %checks { - return ( - message.type === messageTypes.SIDEBAR_SOURCE || - message.type === messageTypes.REACTION || - message.type === messageTypes.EDIT_MESSAGE || - message.type === messageTypes.TOGGLE_PIN - ); -} - const mediaMessageTypes = new Set([ messageTypes.IMAGES, messageTypes.MULTIMEDIA,