Skip to content

Commit

Permalink
feat: update self supported protocols [WPB-2174] (#15399)
Browse files Browse the repository at this point in the history
* feat: periodically check migration config [FS-1893] (#15117)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: start migration of proteus conversations [FS-1888] (#15198)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: initialise migration of proteus conversations

* feat: create mls group after switching to mixed and add other clients

* runfix: send messages with mls if conversation is actually mls (not if group id exists)

* chore: bump core

* refactor: don't replace conversation's reference

* feat: insert system message after conversation protocol update

* refactor: improve reaction to protocol update event

* refactor: move protocol update logic to conversation repository

* feat: save conversation state to db after updating protocol

* feat: update conversation protocol-related fields after protocol was updated

* refactor: move adding users of conversation to separate module

* refactor: move establishing group for mixed conversation to separate module

* chore: update comments

* runfix: don't try to to add users to mls group if mixed conv is empty

* test: adding all conversation members to mls group

* test: try establishing mls group for mixed conversation

* chore: remove comment

* test: conversation repo updateConversationProtocol

* test: initialise migration of proteus conversations

* refactor: CR suggestions

* feat: automatically join mixed conversations [FS-1897] (#15248)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: initialise migration of proteus conversations

* feat: create mls group after switching to mixed and add other clients

* feat: periodically check migration config [FS-1893] (#15117)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* runfix: send messages with mls if conversation is actually mls (not if group id exists)

* chore: bump core

* refactor: don't replace conversation's reference

* feat: insert system message after conversation protocol update

* refactor: improve reaction to protocol update event

* refactor: move protocol update logic to conversation repository

* feat: save conversation state to db after updating protocol

* feat: update conversation protocol-related fields after protocol was updated

* refactor: move adding users of conversation to separate module

* refactor: move establishing group for mixed conversation to separate module

* chore: update comments

* runfix: don't try to to add users to mls group if mixed conv is empty

* test: adding all conversation members to mls group

* test: try establishing mls group for mixed conversation

* chore: remove comment

* test: conversation repo updateConversationProtocol

* test: initialise migration of proteus conversations

* refactor: CR suggestions

* feat: join unestablished mixed conversations

* test: join unestablished mixed conversations

* feat: periodically check migration config [FS-1893] (#15117)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: start migration of proteus conversations [FS-1888] (#15198)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: initialise migration of proteus conversations

* feat: create mls group after switching to mixed and add other clients

* runfix: send messages with mls if conversation is actually mls (not if group id exists)

* chore: bump core

* refactor: don't replace conversation's reference

* feat: insert system message after conversation protocol update

* refactor: improve reaction to protocol update event

* refactor: move protocol update logic to conversation repository

* feat: save conversation state to db after updating protocol

* feat: update conversation protocol-related fields after protocol was updated

* refactor: move adding users of conversation to separate module

* refactor: move establishing group for mixed conversation to separate module

* chore: update comments

* runfix: don't try to to add users to mls group if mixed conv is empty

* test: adding all conversation members to mls group

* test: try establishing mls group for mixed conversation

* chore: remove comment

* test: conversation repo updateConversationProtocol

* test: initialise migration of proteus conversations

* refactor: CR suggestions

* chore: improve logs in add users method

* chore: bump core

* runfix: filter duplicated system messages (#15264)

* feat: maintain mls group list during migration [WPB-1115] (#15318)

* feat: wipe mls group if user is removed / leave mls-capable conversation

* feat: add users to mls group when conversation is mixed

* feat: restart periodic key material timers on app reload

* test: adding users to mls/mixed/proteus group

* test: add users to mls group

* runfix: joining mls capable conversations

* test: remove / leave conversation

* runfix: add users to mixed conversation

* runfix: show unestablished mixed conversations

* refactor: test

* refactor: apply cr suggestion

* refactor: add MLSCapableConversation type

* test: fix test

* chore: bump core with draft-20 corecrypto

* chore: bump core

* feat: debug util to update migration feature team settings config

* feat: add qa debug util for displaying epoch info

* refactor: reuse existing functionality of joining mls conv with ext commit

* runfix: welcome message not being sent in self conversation anymore

* feat: parse supported protocols (#15379)

* feat: periodically check migration config [FS-1893] (#15117)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: start migration of proteus conversations [FS-1888] (#15198)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: initialise migration of proteus conversations

* feat: create mls group after switching to mixed and add other clients

* runfix: send messages with mls if conversation is actually mls (not if group id exists)

* chore: bump core

* refactor: don't replace conversation's reference

* feat: insert system message after conversation protocol update

* refactor: improve reaction to protocol update event

* refactor: move protocol update logic to conversation repository

* feat: save conversation state to db after updating protocol

* feat: update conversation protocol-related fields after protocol was updated

* refactor: move adding users of conversation to separate module

* refactor: move establishing group for mixed conversation to separate module

* chore: update comments

* runfix: don't try to to add users to mls group if mixed conv is empty

* test: adding all conversation members to mls group

* test: try establishing mls group for mixed conversation

* chore: remove comment

* test: conversation repo updateConversationProtocol

* test: initialise migration of proteus conversations

* refactor: CR suggestions

* feat: automatically join mixed conversations [FS-1897] (#15248)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: initialise migration of proteus conversations

* feat: create mls group after switching to mixed and add other clients

* feat: periodically check migration config [FS-1893] (#15117)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* runfix: send messages with mls if conversation is actually mls (not if group id exists)

* chore: bump core

* refactor: don't replace conversation's reference

* feat: insert system message after conversation protocol update

* refactor: improve reaction to protocol update event

* refactor: move protocol update logic to conversation repository

* feat: save conversation state to db after updating protocol

* feat: update conversation protocol-related fields after protocol was updated

* refactor: move adding users of conversation to separate module

* refactor: move establishing group for mixed conversation to separate module

* chore: update comments

* runfix: don't try to to add users to mls group if mixed conv is empty

* test: adding all conversation members to mls group

* test: try establishing mls group for mixed conversation

* chore: remove comment

* test: conversation repo updateConversationProtocol

* test: initialise migration of proteus conversations

* refactor: CR suggestions

* feat: join unestablished mixed conversations

* test: join unestablished mixed conversations

* feat: periodically check migration config [FS-1893] (#15117)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: start migration of proteus conversations [FS-1888] (#15198)

* feat: base for initialisation and finalisation methods

* feat: check if migration time has arrived after mls is supported

* refactor: improve init migration api

* refactor: rename func

* refactor: move initialisation and finalisation to separate modules

* runfix: start migration flow in background after app was initialised

* feat: filter unestablished mls conversations out

* feat: filter out only mls conversations that are unestablished

* refactor: move mls migration logger to separate file

* feat: update conversation locally

* chore: remove migration init code (follow-up pr)

* refactor: resolve core and api client in module

* feat: read feature config from teamstate

* chore: update core

* runfix: check fresh migration config when timer elapses

* chore: update comment

* refactor: use reduce for grouping conversations by protocol

* refactor: simplify removal key check

* feat: update core with new migration config types

* refactor: improve types

* feat: initialise migration of proteus conversations

* feat: create mls group after switching to mixed and add other clients

* runfix: send messages with mls if conversation is actually mls (not if group id exists)

* chore: bump core

* refactor: don't replace conversation's reference

* feat: insert system message after conversation protocol update

* refactor: improve reaction to protocol update event

* refactor: move protocol update logic to conversation repository

* feat: save conversation state to db after updating protocol

* feat: update conversation protocol-related fields after protocol was updated

* refactor: move adding users of conversation to separate module

* refactor: move establishing group for mixed conversation to separate module

* chore: update comments

* runfix: don't try to to add users to mls group if mixed conv is empty

* test: adding all conversation members to mls group

* test: try establishing mls group for mixed conversation

* chore: remove comment

* test: conversation repo updateConversationProtocol

* test: initialise migration of proteus conversations

* refactor: CR suggestions

* chore: improve logs in add users method

* chore: bump core

* runfix: filter duplicated system messages (#15264)

* feat: maintain mls group list during migration [WPB-1115] (#15318)

* feat: wipe mls group if user is removed / leave mls-capable conversation

* feat: add users to mls group when conversation is mixed

* feat: restart periodic key material timers on app reload

* test: adding users to mls/mixed/proteus group

* test: add users to mls group

* runfix: joining mls capable conversations

* test: remove / leave conversation

* runfix: add users to mixed conversation

* runfix: show unestablished mixed conversations

* refactor: test

* refactor: apply cr suggestion

* refactor: add MLSCapableConversation type

* test: fix test

* chore: bump core with draft-20 corecrypto

* chore: bump core

* feat: debug util to update migration feature team settings config

* feat: add qa debug util for displaying epoch info

* refactor: reuse existing functionality of joining mls conv with ext commit

* runfix: welcome message not being sent in self conversation anymore

* feat: add supportedProtocols field on user entity

* chore: bump core to beta

* feat: evaluate self supported protocols

* test: evaluate supported protocols scenarios

* feat: wrap updating supported protocols with try catch and add logs

* test: supported protocols

* chore: bump core

* refactor: simplify mls migration feature status check

* runfix: return both protocols by default

* refactor: address pr comments
  • Loading branch information
PatrykBuniX committed Jun 28, 2023
1 parent 1a328e2 commit 110bdd7
Show file tree
Hide file tree
Showing 12 changed files with 691 additions and 10 deletions.
1 change: 0 additions & 1 deletion src/script/conversation/ConversationRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2981,7 +2981,6 @@ export class ConversationRepository {
if (changes) {
this.eventService.updateEventSequentially(messageEntity.primary_key, changes);
}
return;
} catch (error) {
const isNotFound = error.type === ConversationError.TYPE.MESSAGE_NOT_FOUND;
if (!isNotFound) {
Expand Down
7 changes: 7 additions & 0 deletions src/script/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import {IntegrationService} from '../integration/IntegrationService';
import {startNewVersionPolling} from '../lifecycle/newVersionHandler';
import {MediaRepository} from '../media/MediaRepository';
import {initMLSCallbacks, initMLSConversations, registerUninitializedSelfAndTeamConversations} from '../mls';
import {initialisePeriodicSelfSupportedProtocolsCheck} from '../mls/supportedProtocols';
import {NotificationRepository} from '../notification/NotificationRepository';
import {PreferenceNotificationRepository} from '../notification/PreferenceNotificationRepository';
import {PermissionRepository} from '../permission/PermissionRepository';
Expand All @@ -94,6 +95,7 @@ import {Core} from '../service/CoreSingleton';
import {StorageKey, StorageRepository, StorageService} from '../storage';
import {TeamRepository} from '../team/TeamRepository';
import {TeamService} from '../team/TeamService';
import {TeamState} from '../team/TeamState';
import {AppInitStatisticsValue} from '../telemetry/app_init/AppInitStatisticsValue';
import {AppInitTelemetry} from '../telemetry/app_init/AppInitTelemetry';
import {AppInitTimingsStep} from '../telemetry/app_init/AppInitTimingsStep';
Expand Down Expand Up @@ -474,6 +476,11 @@ export class App {
callingRepository.setReady();
telemetry.timeStep(AppInitTimingsStep.APP_LOADED);

const teamState = container.resolve(TeamState);
await initialisePeriodicSelfSupportedProtocolsCheck(selfUser, teamState.teamFeatures(), {
userRepository: this.repository.user,
});

this.logger.info(`App loaded in ${Date.now() - startTime}ms`);

return selfUser;
Expand Down
16 changes: 7 additions & 9 deletions src/script/mls/MLSMigration/MLSMigration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/

import {CONVERSATION_TYPE} from '@wireapp/api-client/lib/conversation';
import {FeatureStatus} from '@wireapp/api-client/lib/team';
import {QualifiedId} from '@wireapp/api-client/lib/user';
import {registerRecurringTask} from '@wireapp/core/lib/util/RecurringTaskScheduler';
import {container} from 'tsyringe';
Expand All @@ -36,6 +35,7 @@ import {TIME_IN_MILLIS} from 'Util/TimeUtil';

import {initialiseMigrationOfProteusConversations} from './initialiseMigration';
import {joinUnestablishedMixedConversations} from './initialiseMigration/joinUnestablishedMixedConversations';
import {getMLSMigrationStatus, MLSMigrationStatus} from './migrationStatus';
import {mlsMigrationLogger} from './MLSMigrationLogger';

import {isMLSSupportedByEnvironment} from '../isMLSSupportedByEnvironment';
Expand Down Expand Up @@ -110,26 +110,24 @@ const checkMigrationConfig = async (
if (!isMLSSupportedByEnv) {
return;
}
//at this point we know that MLS is supported by environment, we can check MLS migration config
//at this point we know that MLS is supported by environment, we can check MLS migration status

//fetch current mls migration feature config from memory
const mlsMigrationFeature = teamState.teamFeatures().mlsMigration;
const migrationStatus = getMLSMigrationStatus(mlsMigrationFeature);

if (!mlsMigrationFeature || mlsMigrationFeature.status === FeatureStatus.DISABLED) {
if (migrationStatus === MLSMigrationStatus.DISABLED) {
mlsMigrationLogger.info('MLS migration feature is disabled, will retry in 24 hours or on next app reload.');
return;
}

mlsMigrationLogger.info('MLS migration feature enabled, checking the configuration...');

//if startTime is not defined, we never start the migration, will retry in 24 hours or on next app reload
const startDateISO = mlsMigrationFeature.config.startTime;
const startTime = (startDateISO && Date.parse(startDateISO)) || Infinity;
const hasStartTimeArrived = Date.now() >= startTime;

if (!hasStartTimeArrived) {
if (migrationStatus === MLSMigrationStatus.NOT_STARTED) {
mlsMigrationLogger.info(
'MLS migration start time has not arrived yet, will retry in 24 hours or on next app reload.',
);
return;
}

mlsMigrationLogger.info(
Expand Down
68 changes: 68 additions & 0 deletions src/script/mls/MLSMigration/migrationStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {FeatureMLSMigration, FeatureStatus} from '@wireapp/api-client/lib/team';

const hasMigrationStartTimeArrived = (mlsMigrationFeature: FeatureMLSMigration): boolean => {
if (mlsMigrationFeature.status === FeatureStatus.DISABLED) {
return false;
}

const startDateISO = mlsMigrationFeature.config.startTime;
const startTime = startDateISO ? Date.parse(startDateISO) : Infinity;

return Date.now() >= startTime;
};

const hasMigrationFinaliseRegardlessAfterDateArrived = (mlsMigrationFeature: FeatureMLSMigration): boolean => {
if (mlsMigrationFeature.status === FeatureStatus.DISABLED) {
return false;
}

const finaliseDateISO = mlsMigrationFeature.config.finaliseRegardlessAfter;
const finaliseTime = finaliseDateISO ? Date.parse(finaliseDateISO) : Infinity;

return Date.now() >= finaliseTime;
};

export enum MLSMigrationStatus {
DISABLED = 'DISABLED', //migration feature is disabled
NOT_STARTED = 'NOT_STARTED', //migration feature is enabled but startTime has not arrived
ONGOING = 'ONGOING', //migration feature is enabled and startTime has arrived, but finaliseRegardlessAfter has not arrived
FINALISED = 'FINALISED', //migration feature is enabled and finaliseRegardlessAfter has arrived
}

export const getMLSMigrationStatus = (mlsMigrationFeature?: FeatureMLSMigration): MLSMigrationStatus => {
if (!mlsMigrationFeature || mlsMigrationFeature.status === FeatureStatus.DISABLED) {
return MLSMigrationStatus.DISABLED;
}

const hasMigrationStarted = hasMigrationStartTimeArrived(mlsMigrationFeature);
const hasMigrationEnded = hasMigrationFinaliseRegardlessAfterDateArrived(mlsMigrationFeature);

if (hasMigrationStarted && !hasMigrationEnded) {
return MLSMigrationStatus.ONGOING;
}

if (hasMigrationEnded) {
return MLSMigrationStatus.FINALISED;
}

return MLSMigrationStatus.NOT_STARTED;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {RegisteredClient} from '@wireapp/api-client/lib/client';
import {ConversationProtocol} from '@wireapp/api-client/lib/conversation';
import {FeatureList, FeatureStatus} from '@wireapp/api-client/lib/team';
import {container} from 'tsyringe';

import {APIClient} from '@wireapp/api-client';

import {Core} from 'src/script/service/CoreSingleton';
import {TIME_IN_MILLIS} from 'Util/TimeUtil';

import {evaluateSelfSupportedProtocols} from './evaluateSelfSupportedProtocols';

import * as mlsSupport from '../../isMLSSupportedByEnvironment';
import {MLSMigrationStatus} from '../../MLSMigration/migrationStatus';

jest.spyOn(mlsSupport, 'isMLSSupportedByEnvironment').mockResolvedValue(true);

const generateMLSFeaturesConfig = (migrationStatus: MLSMigrationStatus, supportedProtocols: ConversationProtocol[]) => {
const now = Date.now();

switch (migrationStatus) {
case MLSMigrationStatus.DISABLED:
return {
mls: {
status: FeatureStatus.ENABLED,
config: {supportedProtocols},
},
mlsMigration: {status: FeatureStatus.DISABLED, config: {}},
};
case MLSMigrationStatus.NOT_STARTED:
return {
mls: {
status: FeatureStatus.ENABLED,
config: {supportedProtocols},
},
mlsMigration: {
status: FeatureStatus.ENABLED,
config: {
startTime: new Date(now + 1 * TIME_IN_MILLIS.DAY).toISOString(),
finaliseRegardlessAfter: new Date(now + 2 * TIME_IN_MILLIS.DAY).toISOString(),
},
},
};
case MLSMigrationStatus.ONGOING:
return {
mls: {
status: FeatureStatus.ENABLED,
config: {supportedProtocols},
},
mlsMigration: {
status: FeatureStatus.ENABLED,
config: {
startTime: new Date(now - 1 * TIME_IN_MILLIS.DAY).toISOString(),
finaliseRegardlessAfter: new Date(now + 1 * TIME_IN_MILLIS.DAY).toISOString(),
},
},
};
case MLSMigrationStatus.FINALISED:
return {
mls: {
status: FeatureStatus.ENABLED,
config: {supportedProtocols},
},
mlsMigration: {
status: FeatureStatus.ENABLED,
config: {
startTime: new Date(now - 2 * TIME_IN_MILLIS.DAY).toISOString(),
finaliseRegardlessAfter: new Date(now - 1 * TIME_IN_MILLIS.DAY).toISOString(),
},
},
};
}
};

const createMockClientResponse = (doesSupportMLS = false, wasActiveWithinLast4Weeks = false) => {
return {
mls_public_keys: doesSupportMLS ? {ed25519: 'key'} : undefined,
last_active: wasActiveWithinLast4Weeks
? new Date().toISOString()
: new Date(Date.now() - 5 * 7 * 24 * 60 * 60 * 1000).toISOString(),
} as unknown as RegisteredClient;
};

const generateListOfSelfClients = ({allActiveClientsMLSCapable}: {allActiveClientsMLSCapable: boolean}) => {
const clients: RegisteredClient[] = [];

new Array(4).fill(0).forEach(() => clients.push(createMockClientResponse(true, true)));
if (!allActiveClientsMLSCapable) {
new Array(2).fill(0).forEach(() => clients.push(createMockClientResponse(false, true)));
}

return clients;
};

const testScenarios = [
[
//with given config
generateMLSFeaturesConfig(MLSMigrationStatus.DISABLED, [ConversationProtocol.PROTEUS]),

//we expect the following result based on whether all active clients are MLS capable or not
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.PROTEUS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.PROTEUS]),
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.DISABLED, [ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.PROTEUS]),
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.DISABLED, [ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([]), //FIXME: This may be [ConversationProtocol.PROTEUS]
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.NOT_STARTED, [ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.PROTEUS]),
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.NOT_STARTED, [ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.PROTEUS]),
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.ONGOING, [ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.PROTEUS]),
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.ONGOING, [ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.PROTEUS]),
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.FINALISED, [ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.PROTEUS, ConversationProtocol.MLS]),
},
],
[
generateMLSFeaturesConfig(MLSMigrationStatus.FINALISED, [ConversationProtocol.MLS]),
{
allActiveClientsMLSCapable: new Set([ConversationProtocol.MLS]),
someActiveClientsNotMLSCapable: new Set([ConversationProtocol.MLS]),
},
],
] as const;

describe('evaluateSelfSupportedProtocols', () => {
describe.each([{allActiveClientsMLSCapable: true}, {allActiveClientsMLSCapable: false}])(
'%o',
({allActiveClientsMLSCapable}) => {
const selfClients = generateListOfSelfClients({allActiveClientsMLSCapable});

it.each(testScenarios)('evaluates self supported protocols', async ({mls, mlsMigration}, expected) => {
const mockedApiClient = {api: {client: {getClients: jest.fn()}}} as unknown as APIClient;
const mockCore = container.resolve(Core);

jest.spyOn(mockedApiClient.api.client, 'getClients').mockResolvedValueOnce(selfClients);

const teamFeatureList = {
mlsMigration,
mls,
} as unknown as FeatureList;

const supportedProtocols = await evaluateSelfSupportedProtocols({
apiClient: mockedApiClient,
core: mockCore,
teamFeatureList,
});

expect(supportedProtocols).toEqual(
allActiveClientsMLSCapable ? expected.allActiveClientsMLSCapable : expected.someActiveClientsNotMLSCapable,
);
});
},
);
});
Loading

0 comments on commit 110bdd7

Please sign in to comment.