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 @@ -9,8 +9,11 @@ ThreadPermissionsInfo, ThreadRolePermissionsBlob, } from '../types/thread-permission-types.js'; -import type { RoleInfo } from '../types/thread-types.js'; -import { roleInfoValidator } from '../types/thread-types.js'; +import type { RoleInfo, ThreadCurrentUserInfo } from '../types/thread-types.js'; +import { + roleInfoValidator, + threadCurrentUserInfoValidator, +} from '../types/thread-types.js'; import { entries, invertObjectToMap } from '../utils/objects.js'; import { tRegex, tShape } from '../utils/validation-utils.js'; import type { TRegex } from '../utils/validation-utils.js'; @@ -196,6 +199,18 @@ permissions: t.list(tHexEncodedRolePermission), }); +export type MinimallyEncodedThreadCurrentUserInfo = { + ...ThreadCurrentUserInfo, + +permissions: string, +}; + +const tHexEncodedPermissionsBitmask: TRegex = tRegex(/^[0-9a-fA-F]+$/); +const minimallyEncodedThreadCurrentUserInfoValidator: TInterface = + tShape({ + ...threadCurrentUserInfoValidator.meta.props, + permissions: tHexEncodedPermissionsBitmask, + }); + export { permissionsToBitmaskHex, hasPermission, @@ -204,4 +219,5 @@ threadRolePermissionsBlobToBitmaskArray, decodeThreadRolePermissionsBitmaskArray, minimallyEncodedRoleInfoValidator, + minimallyEncodedThreadCurrentUserInfoValidator, }; 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 @@ -5,6 +5,7 @@ decodeThreadRolePermissionsBitmaskArray, hasPermission, minimallyEncodedRoleInfoValidator, + minimallyEncodedThreadCurrentUserInfoValidator, permissionsToBitmaskHex, rolePermissionToBitmaskHex, threadRolePermissionsBlobToBitmaskArray, @@ -282,3 +283,43 @@ ).toBe(false); }); }); + +describe('minimallyEncodedThreadCurrentUserInfoValidator', () => { + it('should validate correctly formed MinimallyEncodedThreadCurrentUserInfo', () => { + expect( + minimallyEncodedThreadCurrentUserInfoValidator.is({ + permissions: '100', + subscription: { home: true, pushNotifs: true }, + }), + ).toBe(true); + expect( + minimallyEncodedThreadCurrentUserInfoValidator.is({ + permissions: 'ABCDEFABCDEFABCD', + subscription: { home: true, pushNotifs: true }, + }), + ).toBe(true); + }); + + it('should NOT validate malformed MinimallyEncodedThreadCurrentUserInfo', () => { + expect( + minimallyEncodedThreadCurrentUserInfoValidator.is({ + permissions: 'INVALID', + subscription: { home: true, pushNotifs: true }, + }), + ).toBe(false); + + expect( + minimallyEncodedThreadCurrentUserInfoValidator.is({ + permissions: 'ABCDEF hello ABCDEFABCD', + subscription: { home: true, pushNotifs: true }, + }), + ).toBe(false); + + expect( + minimallyEncodedThreadCurrentUserInfoValidator.is({ + permissions: 100, + subscription: { home: true, pushNotifs: true }, + }), + ).toBe(false); + }); +}); 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 @@ -78,12 +78,13 @@ +subscription: ThreadSubscription, +unread: ?boolean, }; -const threadCurrentUserInfoValidator = tShape({ - role: t.maybe(tID), - permissions: threadPermissionsInfoValidator, - subscription: threadSubscriptionValidator, - unread: t.maybe(t.Boolean), -}); +export const threadCurrentUserInfoValidator: TInterface = + tShape({ + role: t.maybe(tID), + permissions: threadPermissionsInfoValidator, + subscription: threadSubscriptionValidator, + unread: t.maybe(t.Boolean), + }); export type RawThreadInfo = { +id: string,