diff --git a/lib/permissions/minimally-encoded-raw-thread-info-validators.js b/lib/permissions/minimally-encoded-raw-thread-info-validators.js --- a/lib/permissions/minimally-encoded-raw-thread-info-validators.js +++ b/lib/permissions/minimally-encoded-raw-thread-info-validators.js @@ -11,6 +11,7 @@ MemberInfoWithPermissions, ThreadCurrentUserInfo, ThinRawThreadInfo, + ThickRawThreadInfo, RoleInfo, RoleInfoWithoutSpecialRole, ThinRawThreadInfoWithoutSpecialRole, @@ -20,9 +21,12 @@ import { threadSubscriptionValidator } from '../types/subscription-types.js'; import { type LegacyThinRawThreadInfo, + type LegacyRawThreadInfo, legacyMemberInfoValidator, legacyThinRawThreadInfoValidator, legacyThreadCurrentUserInfoValidator, + legacyThickRawThreadInfoValidator, + legacyThreadInfoValidator, } from '../types/thread-types.js'; import { tBool, tID, tShape, tUserID } from '../utils/validation-utils.js'; @@ -102,6 +106,15 @@ currentUser: threadCurrentUserInfoValidator, }); +const thickRawThreadInfoValidator: TInterface = + tShape({ + ...legacyThickRawThreadInfoValidator.meta.props, + minimallyEncoded: tBool(true), + members: t.list(minimallyEncodedThickMemberInfoValidator), + roles: t.dict(tID, roleInfoValidator), + currentUser: threadCurrentUserInfoValidator, + }); + const roleInfoWithoutSpecialRolesValidator: TInterface = tShape({ ...roleInfoValidatorBase, @@ -124,6 +137,17 @@ thinRawThreadInfoWithoutSpecialRolesValidator, ]); +const rawThreadInfoValidator: TUnion = + t.union([thinRawThreadInfoValidator, thickRawThreadInfoValidator]); + +const mixedThreadInfoValidator: TUnion< + LegacyRawThreadInfo | ThinRawThreadInfo | ThickRawThreadInfo, +> = t.union([ + legacyThreadInfoValidator, + thinRawThreadInfoValidator, + thickRawThreadInfoValidator, +]); + export { memberInfoWithPermissionsValidator, memberInfoSansPermissionsValidator, @@ -133,4 +157,6 @@ threadCurrentUserInfoValidator, thinRawThreadInfoValidator, mixedThinRawThreadInfoValidator, + mixedThreadInfoValidator, + rawThreadInfoValidator, }; diff --git a/lib/shared/updates/join-thread-spec.js b/lib/shared/updates/join-thread-spec.js --- a/lib/shared/updates/join-thread-spec.js +++ b/lib/shared/updates/join-thread-spec.js @@ -6,7 +6,7 @@ import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; import { createReplaceThreadOperation } from '../../ops/create-replace-thread-operation.js'; -import { mixedThinRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { mixedThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; import { type RawEntryInfo, rawEntryInfoValidator, @@ -168,7 +168,7 @@ type: tNumber(updateTypes.JOIN_THREAD), id: t.String, time: t.Number, - threadInfo: mixedThinRawThreadInfoValidator, + threadInfo: mixedThreadInfoValidator, rawMessageInfos: t.list(rawMessageInfoValidator), truncationStatus: messageTruncationStatusValidator, rawEntryInfos: t.list(rawEntryInfoValidator), diff --git a/lib/shared/updates/update-thread-spec.js b/lib/shared/updates/update-thread-spec.js --- a/lib/shared/updates/update-thread-spec.js +++ b/lib/shared/updates/update-thread-spec.js @@ -6,7 +6,7 @@ import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; import { createReplaceThreadOperation } from '../../ops/create-replace-thread-operation.js'; -import { mixedThinRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { mixedThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; import type { RawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { @@ -112,7 +112,7 @@ type: tNumber(updateTypes.UPDATE_THREAD), id: t.String, time: t.Number, - threadInfo: mixedThinRawThreadInfoValidator, + threadInfo: mixedThreadInfoValidator, }), getUpdatedThreadInfo(update: ThreadUpdateInfo) { return update.threadInfo; diff --git a/lib/types/request-types.js b/lib/types/request-types.js --- a/lib/types/request-types.js +++ b/lib/types/request-types.js @@ -26,13 +26,14 @@ entryInconsistencyReportValidatorShape, } from './report-types.js'; import type { LegacyRawThreadInfo } from './thread-types.js'; +import { legacyThreadInfoValidator } from './thread-types.js'; import { type CurrentUserInfo, currentUserInfoValidator, type AccountUserInfo, accountUserInfoValidator, } from './user-types.js'; -import { mixedThinRawThreadInfoValidator } from '../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { rawThreadInfoValidator } from '../permissions/minimally-encoded-raw-thread-info-validators.js'; import { tNumber, tShape, @@ -164,7 +165,12 @@ ), stateChanges: t.maybe( tShape({ - rawThreadInfos: t.maybe(t.list(mixedThinRawThreadInfoValidator)), + rawThreadInfos: t.maybe( + t.union([ + t.list(legacyThreadInfoValidator), + t.list(rawThreadInfoValidator), + ]), + ), rawEntryInfos: t.maybe(t.list(rawEntryInfoValidator)), currentUserInfo: t.maybe(currentUserInfoValidator), userInfos: t.maybe(t.list(accountUserInfoValidator)), diff --git a/lib/types/socket-types.js b/lib/types/socket-types.js --- a/lib/types/socket-types.js +++ b/lib/types/socket-types.js @@ -54,7 +54,7 @@ type LoggedOutUserInfo, loggedOutUserInfoValidator, } from './user-types.js'; -import { mixedThinRawThreadInfoValidator } from '../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { mixedThreadInfoValidator } from '../permissions/minimally-encoded-raw-thread-info-validators.js'; import { values } from '../utils/objects.js'; import { tShape, tNumber, tID } from '../utils/validation-utils.js'; @@ -224,7 +224,7 @@ }>; const serverFullStateSyncValidator = tShape({ ...baseFullStateSyncValidator.meta.props, - threadInfos: t.dict(tID, mixedThinRawThreadInfoValidator), + threadInfos: t.dict(tID, mixedThreadInfoValidator), currentUserInfo: currentUserInfoValidator, }); diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js --- a/lib/types/thread-types.js +++ b/lib/types/thread-types.js @@ -1,6 +1,6 @@ // @flow -import t, { type TInterface } from 'tcomb'; +import t, { type TInterface, type TUnion } from 'tcomb'; import { type AvatarDBContent, @@ -35,12 +35,13 @@ type ThinThreadType, type ThickThreadType, thinThreadTypeValidator, + thickThreadTypeValidator, } from './thread-types-enum.js'; import type { ClientUpdateInfo, ServerUpdateInfo } from './update-types.js'; import type { UserInfo, UserInfos } from './user-types.js'; import type { SpecialRole } from '../permissions/special-roles.js'; import { type ThreadEntity } from '../utils/entity-text.js'; -import { tID, tShape, tUserID } from '../utils/validation-utils.js'; +import { tID, tShape, tUserID, tBool } from '../utils/validation-utils.js'; export type LegacyMemberInfo = { +id: string, @@ -200,6 +201,43 @@ pinnedCount: t.maybe(t.Number), }); +export const thickMemberInfoValidator: TInterface = + tShape({ + id: tUserID, + role: t.maybe(tID), + permissions: threadPermissionsInfoValidator, + subscription: threadSubscriptionValidator, + isSender: t.Boolean, + }); + +export const legacyThickRawThreadInfoValidator: TInterface = + tShape({ + thick: tBool(true), + id: tID, + type: thickThreadTypeValidator, + name: t.maybe(t.String), + avatar: t.maybe(clientAvatarValidator), + description: t.maybe(t.String), + color: t.String, + creationTime: t.Number, + parentThreadID: t.maybe(tID), + containingThreadID: t.maybe(tID), + members: t.list(thickMemberInfoValidator), + roles: t.dict(tID, clientLegacyRoleInfoValidator), + currentUser: legacyThreadCurrentUserInfoValidator, + sourceMessageID: t.maybe(tID), + repliesCount: t.Number, + pinnedCount: t.maybe(t.Number), + timestamps: threadTimestampsValidator, + }); + +export const legacyThreadInfoValidator: TUnion< + LegacyThinRawThreadInfo | LegacyThickRawThreadInfo, +> = t.union([ + legacyThinRawThreadInfoValidator, + legacyThickRawThreadInfoValidator, +]); + export type MixedRawThreadInfos = { +[id: string]: LegacyRawThreadInfo | RawThreadInfo, }; diff --git a/lib/types/validators/redux-state-validators.js b/lib/types/validators/redux-state-validators.js --- a/lib/types/validators/redux-state-validators.js +++ b/lib/types/validators/redux-state-validators.js @@ -2,7 +2,7 @@ import t, { type TInterface } from 'tcomb'; -import { mixedThinRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { rawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; import { tShape, tID } from '../../utils/validation-utils.js'; import { entryStoreValidator } from '../entry-types.js'; import { inviteLinksStoreValidator } from '../link-types.js'; @@ -22,7 +22,7 @@ export const threadStoreValidator: TInterface = tShape({ - threadInfos: t.dict(tID, mixedThinRawThreadInfoValidator), + threadInfos: t.dict(tID, rawThreadInfoValidator), }); export const initialReduxStateValidator: TInterface = 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 @@ -3,7 +3,7 @@ import t from 'tcomb'; import type { TInterface } from 'tcomb'; -import { mixedThinRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { mixedThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; import { tShape, tID } from '../../utils/validation-utils.js'; import { mediaValidator } from '../media-types.js'; import { @@ -69,7 +69,7 @@ export const roleModificationResultValidator: TInterface = tShape({ - threadInfo: t.maybe(mixedThinRawThreadInfoValidator), + threadInfo: mixedThreadInfoValidator, updatesResult: tShape({ newUpdates: t.list(serverUpdateInfoValidator), }), @@ -77,7 +77,7 @@ export const roleDeletionResultValidator: TInterface = tShape({ - threadInfo: t.maybe(mixedThinRawThreadInfoValidator), + threadInfo: mixedThreadInfoValidator, updatesResult: tShape({ newUpdates: t.list(serverUpdateInfoValidator), }), diff --git a/lib/types/validators/user-validators.js b/lib/types/validators/user-validators.js --- a/lib/types/validators/user-validators.js +++ b/lib/types/validators/user-validators.js @@ -3,7 +3,7 @@ import t, { type TInterface, type TUnion, type TEnums } from 'tcomb'; import { policyTypeValidator } from '../../facts/policies.js'; -import { mixedThinRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { mixedThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; import { tShape, tID, tUserID } from '../../utils/validation-utils.js'; import type { LogOutResponse, @@ -38,7 +38,7 @@ rawMessageInfos: t.list(rawMessageInfoValidator), currentUserInfo: loggedInUserInfoValidator, cookieChange: tShape({ - threadInfos: t.dict(tID, mixedThinRawThreadInfoValidator), + threadInfos: t.dict(tID, mixedThreadInfoValidator), userInfos: t.list(userInfoValidator), }), }); @@ -57,7 +57,7 @@ rawEntryInfos: t.maybe(t.list(rawEntryInfoValidator)), serverTime: t.Number, cookieChange: tShape({ - threadInfos: t.dict(tID, mixedThinRawThreadInfoValidator), + threadInfos: t.dict(tID, mixedThreadInfoValidator), userInfos: t.list(userInfoValidator), }), notAcknowledgedPolicies: t.maybe(t.list(policyTypeValidator)), diff --git a/lib/utils/user-info-extraction-utils.js b/lib/utils/user-info-extraction-utils.js --- a/lib/utils/user-info-extraction-utils.js +++ b/lib/utils/user-info-extraction-utils.js @@ -5,7 +5,7 @@ import { processNewUserIDsActionType } from '../actions/user-actions.js'; import type { CallSingleKeyserverEndpointResponse } from '../keyserver-conn/call-single-keyserver-endpoint.js'; -import { mixedThinRawThreadInfoValidator } from '../permissions/minimally-encoded-raw-thread-info-validators.js'; +import { mixedThreadInfoValidator } from '../permissions/minimally-encoded-raw-thread-info-validators.js'; import type { Endpoint } from '../types/endpoints.js'; import type { Dispatch } from '../types/redux-types.js'; import type { MixedRawThreadInfos } from '../types/thread-types.js'; @@ -33,7 +33,7 @@ const additionalResponseFieldsValidator = tShape({ cookieChange: t.maybe( tShape({ - threadInfos: t.dict(tID, mixedThinRawThreadInfoValidator), + threadInfos: t.dict(tID, mixedThreadInfoValidator), userInfos: t.list(userInfoValidator), cookieInvalidated: t.maybe(t.Boolean), sessionID: t.maybe(t.String),