Skip to content

Commit

Permalink
fix: Parse conversation roles directly from 'conversation.create' eve…
Browse files Browse the repository at this point in the history
…nt [FS-1659] (#14916)
  • Loading branch information
atomrc committed Mar 27, 2023
1 parent 46f5b50 commit 89b74ef
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 43 deletions.
30 changes: 30 additions & 0 deletions src/script/conversation/ConversationMapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
CONVERSATION_TYPE,
Member as MemberBackendData,
OtherMember as OtherMemberBackendData,
DefaultConversationRoleName,
RemoteConversations,
} from '@wireapp/api-client/lib/conversation/';
import {RECEIPT_MODE} from '@wireapp/api-client/lib/conversation/data';
Expand Down Expand Up @@ -101,6 +102,35 @@ describe('ConversationMapper', () => {
expect(conversationEntity.last_server_timestamp()).toBe(initialTimestamp);
});

it('maps a backend conversation roles', () => {
const conversation = {
...entities.conversation,
roles: undefined,
members: {
self: {...entities.conversation.members.self, conversation_role: 'wire_admin'},
others: [
{
id: '1',
conversation_role: DefaultConversationRoleName.WIRE_ADMIN,
},
{
id: '2',
conversation_role: DefaultConversationRoleName.WIRE_MEMBER,
},
],
},
};

const initialTimestamp = Date.now();
const [conversationEntity] = ConversationMapper.mapConversations([conversation], initialTimestamp);

expect(conversationEntity.roles()).toEqual({
[conversation.members.self.id]: DefaultConversationRoleName.WIRE_ADMIN,
[conversation.members.others[0].id]: DefaultConversationRoleName.WIRE_ADMIN,
[conversation.members.others[1].id]: DefaultConversationRoleName.WIRE_MEMBER,
});
});

it('maps multiple conversations', () => {
const conversations = payload.conversations.get.conversations;
const conversationEntities = ConversationMapper.mapConversations(conversations);
Expand Down
23 changes: 21 additions & 2 deletions src/script/conversation/ConversationMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,14 @@ export interface SelfStatusUpdateDatabaseData {
verification_state: number;
}

type Roles = {[userId: string]: DefaultConversationRoleName | string};
export type ConversationDatabaseData = ConversationRecord &
Partial<ConversationBackendData> & {
accessModes?: CONVERSATION_ACCESS[];
//CONVERSATION_LEGACY_ACCESS_ROLE for api <= v2, CONVERSATION_ACCESS_ROLE[] since api v3
accessRole?: CONVERSATION_LEGACY_ACCESS_ROLE | CONVERSATION_ACCESS_ROLE[];
accessRoleV2?: CONVERSATION_ACCESS_ROLE[];
roles: {[userId: string]: DefaultConversationRoleName | string};
roles: Roles;
status: ConversationStatus;
team_id: string;
};
Expand Down Expand Up @@ -206,6 +207,24 @@ export class ConversationMapper {
return conversationEntity;
}

private static computeRoles(conversationData: ConversationBackendData | ConversationDatabaseData): Roles {
if ('roles' in conversationData && conversationData.roles) {
return conversationData.roles;
}
const {members} = conversationData;

const allMembers = [...(members?.others ?? []), members?.self];
return allMembers.reduce<Record<string, string>>((roles, member) => {
if (!member || !member.conversation_role) {
return roles;
}
return {
...roles,
[member.id]: member.conversation_role,
};
}, {});
}

private static createConversationEntity(
conversationData: ConversationDatabaseData,
initialTimestamp?: number,
Expand All @@ -225,7 +244,7 @@ export class ConversationMapper {
conversationData.domain || conversationData.qualified_id?.domain,
protocol,
);
conversationEntity.roles(conversationData.roles || {});
conversationEntity.roles(this.computeRoles(conversationData));

conversationEntity.creator = creator;
conversationEntity.groupId = group_id;
Expand Down
8 changes: 0 additions & 8 deletions src/script/conversation/ConversationRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2394,14 +2394,6 @@ export class ConversationRepository {

const creatorIsParticipant = createdByParticipant || createdBySelfUser;

const data = await this.conversationService.getConversationById(conversationEntity);
const allMembers = [...data.members.others, data.members.self];
const conversationRoles = allMembers.reduce<Record<string, string>>((roles, member) => {
roles[member.id] = member.conversation_role;
return roles;
}, {});
conversationEntity.roles(conversationRoles);

if (!creatorIsParticipant) {
(messageEntity as MemberMessage).memberMessageType = SystemMessageType.CONVERSATION_RESUME;
}
Expand Down
20 changes: 1 addition & 19 deletions src/script/conversation/ConversationRoleRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
*/

import {ConversationRole, DefaultConversationRoleName as DefaultRole} from '@wireapp/api-client/lib/conversation/';
import {DefaultConversationRoleName as DefaultRole} from '@wireapp/api-client/lib/conversation/';

import {createRandomUuid} from 'Util/util';

Expand Down Expand Up @@ -71,24 +71,6 @@ describe('ConversationRoleRepository', () => {
});
});

describe('setConversationRoles', () => {
it('sets conversation roles', async () => {
const newRoles: ConversationRole[] = [
{
actions: [Permissions.leaveConversation],
conversation_role: DefaultRole.WIRE_MEMBER,
},
];

const conversationEntity = new Conversation();
roleRepository.setConversationRoles(conversationEntity, newRoles);

const realRoles = roleRepository.getConversationRoles(conversationEntity);

expect(realRoles.length).toBe(1);
});
});

describe('canAddParticipants', () => {
it('checks if a user can add participants to a group', async () => {
const conversationEntity = new Conversation(createRandomUuid());
Expand Down
18 changes: 4 additions & 14 deletions src/script/conversation/ConversationRoleRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ const defaultMemberRole: ConversationRole = {
};

export class ConversationRoleRepository {
readonly conversationRoles: Record<string, ConversationRole[]>;
readonly logger: Logger;
teamRoles: ConversationRole[];

Expand All @@ -74,7 +73,6 @@ export class ConversationRoleRepository {
private readonly teamState = container.resolve(TeamState),
) {
this.logger = getLogger('ConversationRoleRepository');
this.conversationRoles = {};
this.teamRoles = [defaultAdminRole, defaultMemberRole];
}

Expand All @@ -89,10 +87,6 @@ export class ConversationRoleRepository {
}
};

readonly setConversationRoles = (conversation: Conversation, newRoles: ConversationRole[]): void => {
this.conversationRoles[conversation.id] = newRoles;
};

updateConversationRoles = async (conversation: Conversation): Promise<void> => {
const remoteConversationData = await this.conversationService.getConversationById(conversation);
const roleUpdates: Record<string, string> = {};
Expand Down Expand Up @@ -122,26 +116,22 @@ export class ConversationRoleRepository {
});
};

readonly getUserRole = (conversation: Conversation, userEntity: User): string => {
private readonly getUserRole = (conversation: Conversation, userEntity: User): string => {
return conversation.roles()[userEntity.id];
};

readonly isUserGroupAdmin = (conversation: Conversation, userEntity: User): boolean => {
return this.getUserRole(conversation, userEntity) === DefaultRole.WIRE_ADMIN;
};

readonly isSelfGroupAdmin = (conversation: Conversation): boolean => {
return this.isUserGroupAdmin(conversation, this.userState.self());
};

readonly getConversationRoles = (conversation: Conversation): ConversationRole[] => {
private readonly getConversationRoles = (conversation: Conversation): ConversationRole[] => {
if (this.teamState.isTeam() && this.teamState.team()?.id === conversation.team_id) {
return this.teamRoles;
}
return this.conversationRoles[conversation.id] || this.teamRoles;
return this.teamRoles;
};

readonly getUserPermissions = (conversation: Conversation, user: User): ConversationRole => {
private readonly getUserPermissions = (conversation: Conversation, user: User): ConversationRole => {
const conversationRoles = this.getConversationRoles(conversation);
const userRole: string = this.getUserRole(conversation, user);
return conversationRoles?.find(({conversation_role}) => conversation_role === userRole) || defaultMemberRole;
Expand Down

0 comments on commit 89b74ef

Please sign in to comment.