diff --git a/lib/permissions/minimally-encoded-thread-permissions.js b/lib/permissions/minimally-encoded-thread-permissions.js new file mode 100644 --- /dev/null +++ b/lib/permissions/minimally-encoded-thread-permissions.js @@ -0,0 +1,59 @@ +// @flow + +import type { + ThreadPermission, + ThreadPermissionsInfo, +} from '../types/thread-permission-types.js'; +import { entries } from '../utils/objects.js'; + +const minimallyEncodedThreadPermissions = Object.freeze({ + know_of: 0b1, + membership: 0b10, // DEPRECATED + visible: 0b100, + voiced: 0b1000, + edit_entries: 0b10000, + edit_thread: 0b100000, // EDIT_THREAD_NAME + edit_thread_description: 0b1000000, + edit_thread_color: 0b10000000, + delete_thread: 0b100000000, + create_subthreads: 0b1000000000, // CREATE_SUBCHANNELS + create_sidebars: 0b10000000000, + join_thread: 0b100000000000, + edit_permissions: 0b1000000000000, + add_members: 0b10000000000000, + remove_members: 0b100000000000000, + change_role: 0b1000000000000000, + leave_thread: 0b10000000000000000, + react_to_message: 0b100000000000000000, + edit_message: 0b1000000000000000000, + edit_thread_avatar: 0b10000000000000000000, + manage_pins: 0b100000000000000000000, + manage_invite_links: 0b1000000000000000000000, +}); + +const permissionsToBitmask = (permissions: ThreadPermissionsInfo): number => { + let bitmask = 0; + for (const [key, permission] of entries(permissions)) { + if (permission.value && key in minimallyEncodedThreadPermissions) { + bitmask |= minimallyEncodedThreadPermissions[key]; + } + } + return bitmask; +}; + +const hasPermission = ( + permissionsBitmask: number, + permission: ThreadPermission, +): boolean => { + if (!(permission in minimallyEncodedThreadPermissions)) { + return false; + } + const permissionBitmask = minimallyEncodedThreadPermissions[permission]; + return (permissionsBitmask & permissionBitmask) !== 0; +}; + +export { + minimallyEncodedThreadPermissions, + permissionsToBitmask, + hasPermission, +}; diff --git a/lib/permissions/minimally-encoded-thread-permissions.test.js b/lib/permissions/minimally-encoded-thread-permissions.test.js new file mode 100644 --- /dev/null +++ b/lib/permissions/minimally-encoded-thread-permissions.test.js @@ -0,0 +1,55 @@ +// @flow + +import { + hasPermission, + permissionsToBitmask, +} from './minimally-encoded-thread-permissions.js'; + +describe('minimallyEncodedThreadPermissions', () => { + const permissions = { + know_of: { value: true, source: '1' }, + membership: { value: false, source: null }, + visible: { value: true, source: '1' }, + voiced: { value: true, source: '1' }, + edit_entries: { value: true, source: '1' }, + edit_thread: { value: true, source: '1' }, + edit_thread_description: { value: true, source: '1' }, + edit_thread_color: { value: true, source: '1' }, + delete_thread: { value: true, source: '1' }, + create_subthreads: { value: true, source: '1' }, + create_sidebars: { value: true, source: '1' }, + join_thread: { value: false, source: null }, + edit_permissions: { value: false, source: null }, + add_members: { value: true, source: '1' }, + remove_members: { value: true, source: '1' }, + change_role: { value: true, source: '1' }, + leave_thread: { value: false, source: null }, + react_to_message: { value: true, source: '1' }, + edit_message: { value: true, source: '1' }, + }; + + it('should encode ThreadPermissionsInfo as bitmask', () => { + const permissionsBitmask = permissionsToBitmask(permissions); + expect(permissionsBitmask.toString(2)).toBe('1101110011111111101'); + expect(hasPermission(permissionsBitmask, 'know_of')).toBe(true); + expect(hasPermission(permissionsBitmask, 'membership')).toBe(false); + expect(hasPermission(permissionsBitmask, 'visible')).toBe(true); + expect(hasPermission(permissionsBitmask, 'voiced')).toBe(true); + expect(hasPermission(permissionsBitmask, 'edit_entries')).toBe(true); + expect(hasPermission(permissionsBitmask, 'edit_thread')).toBe(true); + expect(hasPermission(permissionsBitmask, 'edit_thread_description')).toBe( + true, + ); + expect(hasPermission(permissionsBitmask, 'edit_thread_color')).toBe(true); + expect(hasPermission(permissionsBitmask, 'delete_thread')).toBe(true); + expect(hasPermission(permissionsBitmask, 'create_subthreads')).toBe(true); + expect(hasPermission(permissionsBitmask, 'create_sidebars')).toBe(true); + expect(hasPermission(permissionsBitmask, 'join_thread')).toBe(false); + expect(hasPermission(permissionsBitmask, 'edit_permissions')).toBe(false); + expect(hasPermission(permissionsBitmask, 'remove_members')).toBe(true); + expect(hasPermission(permissionsBitmask, 'change_role')).toBe(true); + expect(hasPermission(permissionsBitmask, 'leave_thread')).toBe(false); + expect(hasPermission(permissionsBitmask, 'react_to_message')).toBe(true); + expect(hasPermission(permissionsBitmask, 'edit_message')).toBe(true); + }); +});