diff --git a/lib/permissions/minimally-encoded-thread-permissions-test-data.js b/lib/permissions/minimally-encoded-thread-permissions-test-data.js --- a/lib/permissions/minimally-encoded-thread-permissions-test-data.js +++ b/lib/permissions/minimally-encoded-thread-permissions-test-data.js @@ -305,12 +305,14 @@ parentThreadID: '1', members: [ { + minimallyEncoded: true, id: '256', role: null, permissions: '87fff', isSender: false, }, { + minimallyEncoded: true, id: '83853', role: '85172', permissions: '3027f', @@ -319,6 +321,7 @@ ], roles: { '85172': { + minimallyEncoded: true, id: '85172', name: 'Members', permissions: [ @@ -340,6 +343,7 @@ }, }, currentUser: { + minimallyEncoded: true, role: '85172', permissions: '3027f', subscription: { diff --git a/lib/permissions/minimally-encoded-thread-permissions.js b/lib/permissions/minimally-encoded-thread-permissions.js --- a/lib/permissions/minimally-encoded-thread-permissions.js +++ b/lib/permissions/minimally-encoded-thread-permissions.js @@ -220,15 +220,17 @@ ]), ); -export type MinimallyEncodedRoleInfo = { +export type MinimallyEncodedRoleInfo = $ReadOnly<{ ...RoleInfo, + +minimallyEncoded: true, +permissions: $ReadOnlyArray, -}; +}>; const tHexEncodedRolePermission: TRegex = tRegex(/^[0-9a-fA-F]{3,}$/); const minimallyEncodedRoleInfoValidator: TInterface = tShape({ ...roleInfoValidator.meta.props, + minimallyEncoded: tBool(true), permissions: t.list(tHexEncodedRolePermission), }); @@ -236,27 +238,33 @@ roleInfo: RoleInfo, ): MinimallyEncodedRoleInfo => ({ ...roleInfo, + minimallyEncoded: true, permissions: threadRolePermissionsBlobToBitmaskArray(roleInfo.permissions), }); const decodeMinimallyEncodedRoleInfo = ( minimallyEncodedRoleInfo: MinimallyEncodedRoleInfo, -): RoleInfo => ({ - ...minimallyEncodedRoleInfo, - permissions: decodeThreadRolePermissionsBitmaskArray( - minimallyEncodedRoleInfo.permissions, - ), -}); +): RoleInfo => { + const { minimallyEncoded, ...rest } = minimallyEncodedRoleInfo; + return { + ...rest, + permissions: decodeThreadRolePermissionsBitmaskArray( + minimallyEncodedRoleInfo.permissions, + ), + }; +}; -export type MinimallyEncodedThreadCurrentUserInfo = { +export type MinimallyEncodedThreadCurrentUserInfo = $ReadOnly<{ ...ThreadCurrentUserInfo, + +minimallyEncoded: true, +permissions: string, -}; +}>; const tHexEncodedPermissionsBitmask: TRegex = tRegex(/^[0-9a-fA-F]+$/); const minimallyEncodedThreadCurrentUserInfoValidator: TInterface = tShape({ ...threadCurrentUserInfoValidator.meta.props, + minimallyEncoded: tBool(true), permissions: tHexEncodedPermissionsBitmask, }); @@ -264,26 +272,32 @@ threadCurrentUserInfo: ThreadCurrentUserInfo, ): MinimallyEncodedThreadCurrentUserInfo => ({ ...threadCurrentUserInfo, + minimallyEncoded: true, permissions: permissionsToBitmaskHex(threadCurrentUserInfo.permissions), }); const decodeMinimallyEncodedThreadCurrentUserInfo = ( minimallyEncodedThreadCurrentUserInfo: MinimallyEncodedThreadCurrentUserInfo, -): ThreadCurrentUserInfo => ({ - ...minimallyEncodedThreadCurrentUserInfo, - permissions: threadPermissionsFromBitmaskHex( - minimallyEncodedThreadCurrentUserInfo.permissions, - ), -}); +): ThreadCurrentUserInfo => { + const { minimallyEncoded, ...rest } = minimallyEncodedThreadCurrentUserInfo; + return { + ...rest, + permissions: threadPermissionsFromBitmaskHex( + minimallyEncodedThreadCurrentUserInfo.permissions, + ), + }; +}; -export type MinimallyEncodedMemberInfo = { +export type MinimallyEncodedMemberInfo = $ReadOnly<{ ...MemberInfo, + +minimallyEncoded: true, +permissions: string, -}; +}>; const minimallyEncodedMemberInfoValidator: TInterface = tShape({ ...memberInfoValidator.meta.props, + minimallyEncoded: tBool(true), permissions: tHexEncodedPermissionsBitmask, }); @@ -291,30 +305,34 @@ memberInfo: MemberInfo, ): MinimallyEncodedMemberInfo => ({ ...memberInfo, + minimallyEncoded: true, permissions: permissionsToBitmaskHex(memberInfo.permissions), }); const decodeMinimallyEncodedMemberInfo = ( minimallyEncodedMemberInfo: MinimallyEncodedMemberInfo, -): MemberInfo => ({ - ...minimallyEncodedMemberInfo, - permissions: threadPermissionsFromBitmaskHex( - minimallyEncodedMemberInfo.permissions, - ), -}); +): MemberInfo => { + const { minimallyEncoded, ...rest } = minimallyEncodedMemberInfo; + return { + ...rest, + permissions: threadPermissionsFromBitmaskHex( + minimallyEncodedMemberInfo.permissions, + ), + }; +}; -export type MinimallyEncodedRawThreadInfo = { - minimallyEncoded: true, +export type MinimallyEncodedRawThreadInfo = $ReadOnly<{ ...RawThreadInfo, + +minimallyEncoded: true, +members: $ReadOnlyArray, +roles: { +[id: string]: MinimallyEncodedRoleInfo }, +currentUser: MinimallyEncodedThreadCurrentUserInfo, -}; +}>; const minimallyEncodedRawThreadInfoValidator: TInterface = tShape({ - minimallyEncoded: tBool(true), ...rawThreadInfoValidator.meta.props, + minimallyEncoded: tBool(true), members: t.list(minimallyEncodedMemberInfoValidator), roles: t.dict(tID, minimallyEncodedRoleInfoValidator), currentUser: minimallyEncodedThreadCurrentUserInfoValidator, @@ -325,8 +343,8 @@ ): MinimallyEncodedRawThreadInfo => { const { members, roles, currentUser, ...rest } = rawThreadInfo; return { - minimallyEncoded: true, ...rest, + minimallyEncoded: true, members: members.map(minimallyEncodeMemberInfo), roles: _mapValues(minimallyEncodeRoleInfo)(roles), currentUser: minimallyEncodeThreadCurrentUserInfo(currentUser), diff --git a/lib/permissions/minimally-encoded-thread-permissions.test.js b/lib/permissions/minimally-encoded-thread-permissions.test.js --- a/lib/permissions/minimally-encoded-thread-permissions.test.js +++ b/lib/permissions/minimally-encoded-thread-permissions.test.js @@ -277,6 +277,7 @@ it('should validate correctly formed MinimallyEncodedRoleInfo', () => { expect( minimallyEncodedRoleInfoValidator.is({ + minimallyEncoded: true, id: 'roleID', name: 'roleName', permissions: ['abc', 'def'], @@ -337,12 +338,14 @@ it('should validate correctly formed MinimallyEncodedThreadCurrentUserInfo', () => { expect( minimallyEncodedThreadCurrentUserInfoValidator.is({ + minimallyEncoded: true, permissions: '100', subscription: { home: true, pushNotifs: true }, }), ).toBe(true); expect( minimallyEncodedThreadCurrentUserInfoValidator.is({ + minimallyEncoded: true, permissions: 'ABCDEFABCDEFABCD', subscription: { home: true, pushNotifs: true }, }), @@ -352,6 +355,7 @@ it('should NOT validate malformed MinimallyEncodedThreadCurrentUserInfo', () => { expect( minimallyEncodedThreadCurrentUserInfoValidator.is({ + minimallyEncoded: true, permissions: 'INVALID', subscription: { home: true, pushNotifs: true }, }), @@ -359,6 +363,7 @@ expect( minimallyEncodedThreadCurrentUserInfoValidator.is({ + minimallyEncoded: true, permissions: 'ABCDEF hello ABCDEFABCD', subscription: { home: true, pushNotifs: true }, }), @@ -366,6 +371,7 @@ expect( minimallyEncodedThreadCurrentUserInfoValidator.is({ + minimallyEncoded: true, permissions: 100, subscription: { home: true, pushNotifs: true }, }), @@ -377,6 +383,7 @@ it('should validate correctly formed MinimallyEncodedMemberInfo', () => { expect( minimallyEncodedMemberInfoValidator.is({ + minimallyEncoded: true, id: 'memberID', permissions: 'ABCDEF', isSender: true, @@ -385,6 +392,7 @@ expect( minimallyEncodedMemberInfoValidator.is({ + minimallyEncoded: true, id: 'memberID', permissions: '01b', isSender: false, @@ -395,6 +403,7 @@ it('should NOT validate malformed MinimallyEncodedMemberInfo', () => { expect( minimallyEncodedMemberInfoValidator.is({ + minimallyEncoded: true, id: 'memberID', permissions: 'INVALID', isSender: false, @@ -403,6 +412,7 @@ expect( minimallyEncodedMemberInfoValidator.is({ + minimallyEncoded: true, id: 'memberID', permissions: 100, isSender: false,