Page MenuHomePhorge

D12881.1765340459.diff
No OneTemporary

Size
12 KB
Referenced Files
None
Subscribers
None

D12881.1765340459.diff

diff --git a/keyserver/src/responders/thread-responders.js b/keyserver/src/responders/thread-responders.js
--- a/keyserver/src/responders/thread-responders.js
+++ b/keyserver/src/responders/thread-responders.js
@@ -27,8 +27,7 @@
type RoleDeletionRequest,
type RoleDeletionResult,
} from 'lib/types/thread-types.js';
-import { updateUserAvatarRequestValidator } from 'lib/utils/avatar-utils.js';
-import { values } from 'lib/utils/objects.js';
+import { threadSettingsChangesValidator } from 'lib/types/validators/thread-validators.js';
import {
tShape,
tNumEnum,
@@ -118,15 +117,7 @@
export const updateThreadRequestInputValidator: TInterface<UpdateThreadRequest> =
tShape<UpdateThreadRequest>({
threadID: tID,
- changes: tShape({
- type: t.maybe(tNumEnum(values(threadTypes))),
- name: t.maybe(t.String),
- description: t.maybe(t.String),
- color: t.maybe(tColor),
- parentThreadID: t.maybe(tID),
- newMemberIDs: t.maybe(t.list(tUserID)),
- avatar: t.maybe(updateUserAvatarRequestValidator),
- }),
+ changes: threadSettingsChangesValidator,
accountPassword: t.maybe(tPassword),
});
diff --git a/lib/shared/dm-ops/change-thread-settings-spec.js b/lib/shared/dm-ops/change-thread-settings-spec.js
new file mode 100644
--- /dev/null
+++ b/lib/shared/dm-ops/change-thread-settings-spec.js
@@ -0,0 +1,190 @@
+// @flow
+
+import uuid from 'uuid';
+
+import { addMembersSpec } from './add-members-spec.js';
+import type {
+ DMOperationSpec,
+ ProcessDMOperationUtilities,
+} from './dm-op-spec.js';
+import type { DMChangeThreadSettingsOperation } from '../../types/dm-ops.js';
+import { messageTypes } from '../../types/message-types-enum.js';
+import type { RawMessageInfo } from '../../types/message-types.js';
+import type { RawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js';
+import type { LegacyRawThreadInfo } from '../../types/thread-types.js';
+import { updateTypes } from '../../types/update-types-enum.js';
+import type { ClientUpdateInfo } from '../../types/update-types.js';
+import { values } from '../../utils/objects.js';
+import { firstLine } from '../../utils/string-utils.js';
+import { validChatNameRegex } from '../../utils/validation-utils.js';
+
+const changeThreadSettingsSpec: DMOperationSpec<DMChangeThreadSettingsOperation> =
+ Object.freeze({
+ processDMOperation: async (
+ dmOperation: DMChangeThreadSettingsOperation,
+ viewerID: string,
+ utilities: ProcessDMOperationUtilities,
+ ) => {
+ const {
+ editorID,
+ time,
+ changes,
+ messageIDsPrefix,
+ threadInfo,
+ rawMessageInfos,
+ truncationStatus,
+ rawEntryInfos,
+ } = dmOperation;
+ const {
+ name: untrimmedName,
+ description,
+ color,
+ parentThreadID,
+ avatar,
+ type: threadType,
+ } = changes;
+ const threadID = threadInfo.id;
+
+ const newMemberIDs =
+ changes.newMemberIDs && changes.newMemberIDs.length > 0
+ ? [...new Set(changes.newMemberIDs)]
+ : null;
+
+ let threadInfoToUpdate: ?(RawThreadInfo | LegacyRawThreadInfo) =
+ utilities.getThreadInfo(threadID);
+ if (!threadInfoToUpdate && !newMemberIDs?.includes(viewerID)) {
+ // We can't perform this operation now. It should be queued for later.
+ return {
+ rawMessageInfos: [],
+ updateInfos: [],
+ };
+ }
+
+ const updateInfos: Array<ClientUpdateInfo> = [];
+ const generatedRawMessageInfos: Array<RawMessageInfo> = [];
+
+ if (newMemberIDs) {
+ const addMembersResult = await addMembersSpec.processDMOperation(
+ {
+ type: 'add_members',
+ editorID,
+ time,
+ messageID: `${messageIDsPrefix}/add_members`,
+ addedUserIDs: newMemberIDs,
+ threadInfo,
+ rawMessageInfos,
+ truncationStatus,
+ rawEntryInfos,
+ },
+ viewerID,
+ utilities,
+ );
+ const threadInfoFromUpdates = addMembersResult.updateInfos.find(
+ update =>
+ update.type === updateTypes.UPDATE_THREAD ||
+ update.type === updateTypes.JOIN_THREAD,
+ )?.threadInfo;
+ if (threadInfoFromUpdates) {
+ threadInfoToUpdate = threadInfoFromUpdates;
+ }
+ updateInfos.push(...addMembersResult.updateInfos);
+ generatedRawMessageInfos.push(...addMembersResult.rawMessageInfos);
+ }
+
+ if (!threadInfoToUpdate || !threadInfoToUpdate.thick) {
+ // We can't perform this operation now. It should be queued for later.
+ return {
+ rawMessageInfos: [],
+ updateInfos: [],
+ };
+ }
+
+ const changedFields: { [string]: string | number } = {};
+
+ if (untrimmedName !== undefined && untrimmedName !== null) {
+ const name = firstLine(untrimmedName);
+ if (name.search(validChatNameRegex) === -1) {
+ return {
+ rawMessageInfos: [],
+ updateInfos: [],
+ };
+ }
+ changedFields.name = name;
+ threadInfoToUpdate = {
+ ...threadInfoToUpdate,
+ name,
+ };
+ }
+
+ if (description !== undefined && description !== null) {
+ changedFields.description = description;
+ threadInfoToUpdate = {
+ ...threadInfoToUpdate,
+ description,
+ };
+ }
+
+ if (color) {
+ const newColor = color.toLowerCase();
+ changedFields.color = newColor;
+ threadInfoToUpdate = {
+ ...threadInfoToUpdate,
+ color: newColor,
+ };
+ }
+
+ if (parentThreadID !== undefined) {
+ // TODO do we want to support this for thick threads?
+ return {
+ rawMessageInfos: [],
+ updateInfos: [],
+ };
+ }
+
+ if (avatar) {
+ changedFields.avatar =
+ avatar.type !== 'remove' ? JSON.stringify(avatar) : '';
+ threadInfoToUpdate = {
+ ...threadInfoToUpdate,
+ avatar: threadInfo.avatar,
+ };
+ }
+
+ if (threadType !== null && threadType !== undefined) {
+ // TODO do we want to support this for thick threads?
+ return {
+ rawMessageInfos: [],
+ updateInfos: [],
+ };
+ }
+
+ for (const fieldName in changedFields) {
+ const newValue = changedFields[fieldName];
+ generatedRawMessageInfos.push({
+ type: messageTypes.CHANGE_SETTINGS,
+ threadID,
+ creatorID: editorID,
+ time,
+ field: fieldName,
+ value: newValue,
+ id: `${messageIDsPrefix}/${fieldName}`,
+ });
+ }
+
+ if (values(changedFields).length > 0) {
+ updateInfos.push({
+ type: updateTypes.UPDATE_THREAD,
+ id: uuid.v4(),
+ time,
+ threadInfo: threadInfoToUpdate,
+ });
+ }
+
+ return {
+ rawMessageInfos: generatedRawMessageInfos,
+ updateInfos,
+ };
+ },
+ });
+
+export { changeThreadSettingsSpec };
diff --git a/lib/shared/dm-ops/dm-op-specs.js b/lib/shared/dm-ops/dm-op-specs.js
--- a/lib/shared/dm-ops/dm-op-specs.js
+++ b/lib/shared/dm-ops/dm-op-specs.js
@@ -1,6 +1,7 @@
// @flow
import { addMembersSpec } from './add-members-spec.js';
+import { changeThreadSettingsSpec } from './change-thread-settings-spec.js';
import { createSidebarSpec } from './create-sidebar-spec.js';
import { createThreadSpec } from './create-thread-spec.js';
import type { DMOperationSpec } from './dm-op-spec.js';
@@ -24,4 +25,5 @@
[dmOperationTypes.JOIN_THREAD]: joinThreadSpec,
[dmOperationTypes.LEAVE_THREAD]: leaveThreadSpec,
[dmOperationTypes.REMOVE_MEMBERS]: removeMembersSpec,
+ [dmOperationTypes.CHANGE_THREAD_SETTINGS]: changeThreadSettingsSpec,
});
diff --git a/lib/types/dm-ops.js b/lib/types/dm-ops.js
--- a/lib/types/dm-ops.js
+++ b/lib/types/dm-ops.js
@@ -16,7 +16,9 @@
type NonSidebarThickThreadType,
nonSidebarThickThreadTypes,
} from './thread-types-enum.js';
+import type { ThreadChanges } from './thread-types.js';
import type { ClientUpdateInfo } from './update-types.js';
+import { threadSettingsChangesValidator } from './validators/thread-validators.js';
import { threadInfoValidator } from '../permissions/minimally-encoded-thread-permissions-validators.js';
import { values } from '../utils/objects.js';
import { tShape, tString, tUserID } from '../utils/validation-utils.js';
@@ -31,6 +33,7 @@
JOIN_THREAD: 'join_thread',
LEAVE_THREAD: 'leave_thread',
REMOVE_MEMBERS: 'remove_members',
+ CHANGE_THREAD_SETTINGS: 'change_thread_settings',
});
export type DMOperationType = $Values<typeof dmOperationTypes>;
@@ -222,6 +225,30 @@
removedUserIDs: t.list(tUserID),
});
+export type DMChangeThreadSettingsOperation = {
+ +type: 'change_thread_settings',
+ +editorID: string,
+ +time: number,
+ +changes: ThreadChanges,
+ +messageIDsPrefix: string,
+ +threadInfo: ThickRawThreadInfo,
+ +rawMessageInfos: $ReadOnlyArray<RawMessageInfo>,
+ +truncationStatus: MessageTruncationStatus,
+ +rawEntryInfos: $ReadOnlyArray<RawEntryInfo>,
+};
+export const dmChangeThreadSettingsOperation: TInterface<DMChangeThreadSettingsOperation> =
+ tShape<DMChangeThreadSettingsOperation>({
+ type: tString(dmOperationTypes.CHANGE_THREAD_SETTINGS),
+ editorID: tUserID,
+ time: t.Number,
+ changes: threadSettingsChangesValidator,
+ messageIDsPrefix: t.String,
+ threadInfo: threadInfoValidator,
+ rawMessageInfos: t.list(rawMessageInfoValidator),
+ truncationStatus: messageTruncationStatusValidator,
+ rawEntryInfos: t.list(rawEntryInfoValidator),
+ });
+
export type DMOperation =
| DMCreateThreadOperation
| DMCreateSidebarOperation
@@ -231,7 +258,8 @@
| DMAddMembersOperation
| DMJoinThreadOperation
| DMLeaveThreadOperation
- | DMRemoveMembersOperation;
+ | DMRemoveMembersOperation
+ | DMChangeThreadSettingsOperation;
export const dmOperationValidator: TUnion<DMOperation> = t.union([
dmCreateThreadOperationValidator,
dmCreateSidebarOperationValidator,
@@ -242,6 +270,7 @@
dmJoinThreadOperation,
dmLeaveThreadOperation,
dmRemoveMembersOperation,
+ dmChangeThreadSettingsOperation,
]);
export type DMOperationResult = {
diff --git a/lib/types/validators/thread-validators.js b/lib/types/validators/thread-validators.js
--- a/lib/types/validators/thread-validators.js
+++ b/lib/types/validators/thread-validators.js
@@ -4,12 +4,21 @@
import type { TInterface } from 'tcomb';
import { mixedRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js';
-import { tShape, tID } from '../../utils/validation-utils.js';
+import { updateUserAvatarRequestValidator } from '../../utils/avatar-utils.js';
+import { values } from '../../utils/objects.js';
+import {
+ tShape,
+ tID,
+ tNumEnum,
+ tColor,
+ tUserID,
+} from '../../utils/validation-utils.js';
import { mediaValidator } from '../media-types.js';
import {
rawMessageInfoValidator,
messageTruncationStatusesValidator,
} from '../message-types.js';
+import { threadTypes } from '../thread-types-enum.js';
import {
type ChangeThreadSettingsResult,
type LeaveThreadResult,
@@ -19,6 +28,7 @@
type ToggleMessagePinResult,
type RoleModificationResult,
type RoleDeletionResult,
+ type ThreadChanges,
} from '../thread-types.js';
import { serverUpdateInfoValidator } from '../update-types.js';
import { userInfosValidator } from '../user-types.js';
@@ -30,6 +40,17 @@
}),
});
+export const threadSettingsChangesValidator: TInterface<ThreadChanges> =
+ tShape<ThreadChanges>({
+ type: t.maybe(tNumEnum(values(threadTypes))),
+ name: t.maybe(t.String),
+ description: t.maybe(t.String),
+ color: t.maybe(tColor),
+ parentThreadID: t.maybe(tID),
+ newMemberIDs: t.maybe(t.list(tUserID)),
+ avatar: t.maybe(updateUserAvatarRequestValidator),
+ });
+
export const changeThreadSettingsResultValidator: TInterface<ChangeThreadSettingsResult> =
tShape<ChangeThreadSettingsResult>({
newMessageInfos: t.list(rawMessageInfoValidator),

File Metadata

Mime Type
text/plain
Expires
Wed, Dec 10, 4:20 AM (10 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5860904
Default Alt Text
D12881.1765340459.diff (12 KB)

Event Timeline