Skip to content

Commit

Permalink
feat: Check for missing team member when no clients are left (WEBAPP-…
Browse files Browse the repository at this point in the history
  • Loading branch information
ffflorian authored Apr 17, 2020
1 parent b889ea6 commit 604f54e
Showing 1 changed file with 43 additions and 36 deletions.
79 changes: 43 additions & 36 deletions src/script/conversation/ClientMismatchHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {UserRepository} from '../user/UserRepository';
import {EventInfoEntity} from './EventInfoEntity';
import {NewOTRMessage} from '@wireapp/api-client/dist/conversation';
import {Conversation} from '../entity/Conversation';
import {BackendClientError} from '../error/BackendClientError';

export class ClientMismatchHandler {
private readonly conversationRepository: ConversationRepository;
Expand Down Expand Up @@ -73,8 +74,8 @@ export class ClientMismatchHandler {
eventInfoEntity.conversationId !== ''
? await this.conversationRepository.get_conversation_by_id(eventInfoEntity.conversationId)
: undefined;
this.handleRedundant(redundant, payload, conversationEntity);
this.handleDeleted(deleted, payload, conversationEntity);
await this.handleRedundant(redundant, payload, conversationEntity);
await this.handleDeleted(deleted, payload, conversationEntity);
return this.handleMissing(missing, payload, conversationEntity, eventInfoEntity);
}

Expand All @@ -84,27 +85,31 @@ export class ClientMismatchHandler {
* @note Contains clients of which the backend is sure that they should not be recipient of a message and verified they no longer exist.
* @param recipients User client map containing redundant clients
* @param payload Payload of the request
* @param [conversationEntity] Conversation entity
* @param conversationEntity Conversation entity
* @returns Resolves when the payload got updated
*/
private handleDeleted(recipients: UserClients, payload: NewOTRMessage, conversationEntity?: Conversation): void {
private async handleDeleted(
recipients: UserClients,
payload: NewOTRMessage,
conversationEntity?: Conversation,
): Promise<void> {
if (Object.entries(recipients).length === 0) {
return;
}
this.logger.debug(`Message contains deleted clients of '${Object.keys(recipients).length}' users`, recipients);
const removeDeletedClient = (userId: string, clientId: string) => {
const removeDeletedClient = async (userId: string, clientId: string): Promise<void> => {
delete payload.recipients[userId][clientId];
this.userRepository.removeClientFromUser(userId, clientId);
await this.userRepository.removeClientFromUser(userId, clientId);
};
this.removePayload(recipients, removeDeletedClient, conversationEntity, payload, false);
await this.removePayload(recipients, removeDeletedClient, conversationEntity, payload);
}

/**
* Handle the missing client mismatch.
*
* @param recipients User client map containing redundant clients
* @param payload Payload of the request
* @param [conversationEntity] Conversation entity
* @param conversationEntity Conversation entity
* @param eventInfoEntity Info about event
* @returns Resolves with the updated payload
*/
Expand All @@ -117,7 +122,7 @@ export class ClientMismatchHandler {
const missingUserIds = Object.keys(recipients);

if (!missingUserIds.length) {
return Promise.resolve(payload);
return payload;
}

this.logger.debug(`Message is missing clients of '${missingUserIds.length}' users`, recipients);
Expand Down Expand Up @@ -157,16 +162,22 @@ export class ClientMismatchHandler {
* Sometimes clients of the self user are listed. Thus we cannot remove the payload for all the clients of a user without checking.
* @param recipients User client map containing redundant clients
* @param payload Payload of the request
* @param [conversationEntity] Conversation entity
* @param conversationEntity Conversation entity
* @returns Resolves when the payload got updated
*/
private handleRedundant(recipients: UserClients, payload: NewOTRMessage, conversationEntity?: Conversation): void {
private async handleRedundant(
recipients: UserClients,
payload: NewOTRMessage,
conversationEntity?: Conversation,
): Promise<void> {
if (Object.entries(recipients).length === 0) {
return;
}
this.logger.debug(`Message contains redundant clients of '${Object.keys(recipients).length}' users`, recipients);
const removeRedundantClient = (userId: string, clientId: string) => delete payload.recipients[userId][clientId];
this.removePayload(recipients, removeRedundantClient, conversationEntity, payload, true);
const removeRedundantClient = (userId: string, clientId: string) => {
delete payload.recipients[userId][clientId];
};
await this.removePayload(recipients, removeRedundantClient, conversationEntity, payload);
}

/**
Expand All @@ -176,40 +187,36 @@ export class ClientMismatchHandler {
* @param clientFn Function to remove clients
* @param conversationEntity Conversation entity
* @param payload Initial payload resulting in a 412
* @param verifyDeletedUsers Verifies if users still exist on the backend by checking their active clients
* @returns Function array
*/
removePayload(
async removePayload(
recipients: UserClients,
clientFn: Function,
clientFn: (userId: string, clientId: string) => void | Promise<void>,
conversationEntity: Conversation = undefined,
payload: NewOTRMessage,
verifyDeletedUsers: boolean,
): void[] {
const result: void[] = [];

const removeDeletedUser = (userId: string) => {
): Promise<void> {
const removeDeletedUser = async (userId: string): Promise<void> => {
const clientIdsOfUser = Object.keys(payload.recipients[userId]);
const noRemainingClients = !clientIdsOfUser.length;

if (noRemainingClients) {
if (conversationEntity !== undefined) {
if (conversationEntity.isGroup() && verifyDeletedUsers) {
const timestamp = this.serverTimeHandler.toServerTimestamp();
const event = EventBuilder.buildMemberLeave(conversationEntity, userId, false, timestamp);
this.eventRepository.injectEvent(event);
}
if (noRemainingClients && typeof conversationEntity !== 'undefined' && conversationEntity.isGroup()) {
const result = await this.userRepository['userService'].getUser(userId);
const isDeleted = result?.deleted === true;
if (isDeleted) {
const timestamp = this.serverTimeHandler.toServerTimestamp();
const memberLeaveEvent = EventBuilder.buildMemberLeave(conversationEntity, userId, false, timestamp);
this.eventRepository.injectEvent(memberLeaveEvent);
}

delete payload.recipients[userId];
}

delete payload.recipients[userId];
};

Object.entries(recipients).forEach(([userId, clientIds = []]) => {
clientIds.forEach(clientId => result.push(clientFn(userId, clientId)));
result.push(removeDeletedUser(userId));
});
for (const [userId, clientIds = []] of Object.entries(recipients)) {
for (const clientId of clientIds) {
await clientFn(userId, clientId);
}

return result;
await removeDeletedUser(userId);
}
}
}

0 comments on commit 604f54e

Please sign in to comment.