Skip to content

Commit

Permalink
runfix: joining after migration is finalised
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrykBuniX committed Nov 6, 2023
1 parent 5197fd5 commit f0a3c3b
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 129 deletions.
5 changes: 3 additions & 2 deletions src/script/backup/BackupRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,12 @@ describe('BackupRepository', () => {
it('successfully imports a backup', async () => {
const [backupRepository, {backupService, conversationRepository}] = await buildBackupRepository();
const user = new User('user1');
jest.spyOn(backupService, 'getDatabaseVersion').mockReturnValue(15);
const mockedDBVersion = 20;
jest.spyOn(backupService, 'getDatabaseVersion').mockReturnValue(mockedDBVersion);
const importSpy = jest.spyOn(backupService, 'importEntities').mockResolvedValue(1);
const users = [generateAPIUser(), generateAPIUser()];

const metadata = {...backupRepository.createMetaData(user, 'client1'), version: 15};
const metadata = {...backupRepository.createMetaData(user, 'client1'), version: mockedDBVersion};

const files = {
[Filename.METADATA]: JSON.stringify(metadata),
Expand Down
2 changes: 2 additions & 0 deletions src/script/conversation/ConversationFilter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ describe('ConversationFilter', () => {
name: 'Florian@Staging11',
others: ['71e25be1-5433-4647-964d-03a5d9e7c970'],
protocol: ConversationProtocol.PROTEUS,
initial_protocol: ConversationProtocol.PROTEUS,
qualified_others: undefined,
receipt_mode: null,
roles: {},
Expand Down Expand Up @@ -114,6 +115,7 @@ describe('ConversationFilter', () => {
muted_timestamp: 0,
name: 'Florian@Staging11',
others: ['71e25be1-5433-4647-964d-03a5d9e7c970'],
initial_protocol: ConversationProtocol.PROTEUS,
protocol: ConversationProtocol.PROTEUS,
qualified_others: undefined,
receipt_mode: null,
Expand Down
17 changes: 15 additions & 2 deletions src/script/conversation/ConversationMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,20 @@ export class ConversationMapper {
throw new ConversationError(BASE_ERROR_TYPE.INVALID_PARAMETER, BaseError.MESSAGE.INVALID_PARAMETER);
}

const {creator, id, members, name, others, qualified_others, type, group_id, epoch, protocol, cipher_suite} =
conversationData;
const {
creator,
id,
members,
name,
others,
qualified_others,
type,
group_id,
epoch,
protocol,
cipher_suite,
initial_protocol,
} = conversationData;

let conversationEntity = new Conversation(
id,
Expand All @@ -246,6 +258,7 @@ export class ConversationMapper {

conversationEntity.creator = creator;
conversationEntity.groupId = group_id;
conversationEntity.initialProtocol = initial_protocol;
conversationEntity.epoch = epoch ?? -1;
conversationEntity.cipherSuite = cipher_suite;
conversationEntity.type(type);
Expand Down
14 changes: 4 additions & 10 deletions src/script/conversation/ConversationRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -579,15 +579,14 @@ export class ConversationRepository {

/**
* Will load all the conversations in memory
* @param initialLocalConversations conversations stored in the local database
* @returns all the conversations from backend merged with the locally stored conversations and loaded into memory
*/
public async loadConversations(initialLocalConversations?: ConversationDatabaseData[]): Promise<Conversation[]> {
public async loadConversations(): Promise<Conversation[]> {
const remoteConversations = await this.conversationService.getAllConversations().catch(error => {
this.logger.error(`Failed to get all conversations from backend: ${error.message}`);
return {found: []} as RemoteConversations;
});
return this.loadRemoteConversations(remoteConversations, initialLocalConversations);
return this.loadRemoteConversations(remoteConversations);
}

/**
Expand All @@ -613,13 +612,8 @@ export class ConversationRepository {
* @param remoteConversations new conversations fetched from backend
* @returns the new conversations from backend merged with the locally stored conversations
*/
private async loadRemoteConversations(
remoteConversations: RemoteConversations,
initialLocalConversations?: ConversationDatabaseData[],
): Promise<Conversation[]> {
const localConversations =
initialLocalConversations ||
(await this.conversationService.loadConversationStatesFromDb<ConversationDatabaseData>());
private async loadRemoteConversations(remoteConversations: RemoteConversations): Promise<Conversation[]> {
const localConversations = await this.conversationService.loadConversationStatesFromDb<ConversationDatabaseData>();
let conversationsData: any[];

if (!remoteConversations.found?.length) {
Expand Down
3 changes: 3 additions & 0 deletions src/script/entity/Conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ export class Conversation {
public groupId?: string;
public epoch: number = -1;
public cipherSuite: number = 1;
// Initial protocol is a protocol that was known by a webapp before any protocol update happened. For newly created conversations it is the same as protocol.
public initialProtocol: ConversationProtocol = this.protocol;
public readonly display_name: ko.PureComputed<string>;
public readonly firstUserEntity: ko.PureComputed<User | undefined>;
public readonly globalMessageTimer: ko.Observable<number | null>;
Expand Down Expand Up @@ -1005,6 +1007,7 @@ export class Conversation {
epoch: this.epoch,
global_message_timer: this.globalMessageTimer(),
group_id: this.groupId,
initial_protocol: this.initialProtocol,
id: this.id,
is_guest: this.isGuest(),
last_event_timestamp: this.last_event_timestamp(),
Expand Down
9 changes: 2 additions & 7 deletions src/script/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ import {ClientRepository, ClientService} from '../client';
import {Configuration} from '../Config';
import {ConnectionRepository} from '../connection/ConnectionRepository';
import {ConnectionService} from '../connection/ConnectionService';
import {ConversationDatabaseData} from '../conversation/ConversationMapper';
import {ConversationRepository} from '../conversation/ConversationRepository';
import {ConversationService} from '../conversation/ConversationService';
import {MessageRepository} from '../conversation/MessageRepository';
Expand Down Expand Up @@ -423,10 +422,7 @@ export class App {
const connections = await connectionRepository.getConnections();
telemetry.addStatistic(AppInitStatisticsValue.CONNECTIONS, connections.length, 50);

const initialLocalConversations =
await this.service.conversation.loadConversationStatesFromDb<ConversationDatabaseData>();

const conversations = await conversationRepository.loadConversations(initialLocalConversations);
const conversations = await conversationRepository.loadConversations();

await userRepository.loadUsers(selfUser, connections, conversations, teamMembers);

Expand Down Expand Up @@ -463,8 +459,7 @@ export class App {
if (supportsMLSMigration()) {
//join all the mls groups that are known by the user but were migrated to mls
await joinConversationsAfterMigrationFinalisation({
updatedConversations: conversations,
initialDatabaseConversations: initialLocalConversations,
conversations,
core: this.core,
conversationRepository: conversationRepository,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ import {
} from '@wireapp/api-client/lib/conversation';
import {container} from 'tsyringe';

import {ConversationDatabaseData} from 'src/script/conversation/ConversationMapper';
import {Conversation} from 'src/script/entity/Conversation';
import {ConversationDatabaseData, ConversationMapper} from 'src/script/conversation/ConversationMapper';
import {User} from 'src/script/entity/User';
import {CONVERSATION} from 'src/script/event/Client';
import {Core} from 'src/script/service/CoreSingleton';
Expand All @@ -38,6 +37,7 @@ import {joinConversationsAfterMigrationFinalisation} from './';
const createMockedDBConversationEntry = (
id: string,
domain: string,
initialProtocol: ConversationProtocol,
protocol: ConversationProtocol,
type: CONVERSATION_TYPE,
): ConversationDatabaseData => ({
Expand Down Expand Up @@ -65,6 +65,7 @@ const createMockedDBConversationEntry = (
global_message_timer: 0,
group_id: 'AAEAAGzYgfBo4k5Eti33a4ZZ78cAYW50YS53aXJlLmxpbms=',
id,
initial_protocol: initialProtocol,
is_guest: false,
last_event_timestamp: 1688640266515,
last_read_timestamp: 1688640266515,
Expand Down Expand Up @@ -98,12 +99,15 @@ const createMockedDBConversationEntry = (
const createConversation = (
id: string,
domain: string,
initialProtocol: ConversationProtocol,
protocol: ConversationProtocol,
type: CONVERSATION_TYPE,
selfUser: User,
groupId?: string,
) => {
const conversation = new Conversation(id, domain, protocol);
const conversationRecord = createMockedDBConversationEntry(id, domain, initialProtocol, protocol, type);

const [conversation] = ConversationMapper.mapConversations([conversationRecord]);
conversation.type(type);

if (protocol === ConversationProtocol.MLS) {
Expand All @@ -115,20 +119,6 @@ const createConversation = (
return conversation;
};

const createdMigratedConversationEntities = (
id: string,
domain: string,
type: CONVERSATION_TYPE,
selfUser: User,
protocols: {localStore: ConversationProtocol; backend: ConversationProtocol},
groupId?: string,
) => {
return {
conversationDatabaseData: createMockedDBConversationEntry(id, domain, protocols.localStore, type),
updatedConversation: createConversation(id, domain, protocols.backend, type, selfUser, groupId),
};
};

const testFactory = new TestFactory();

describe('joinConversationsAfterMigrationFinalisation', () => {
Expand All @@ -148,21 +138,18 @@ describe('joinConversationsAfterMigrationFinalisation', () => {
const conversationGroupId = 'groupId1';
const selfUser = new User(createUuid());

const {updatedConversation, conversationDatabaseData} = createdMigratedConversationEntities(
const mockedConversation = createConversation(
conversationId,
mockDomain,
ConversationProtocol.PROTEUS,
ConversationProtocol.MLS,
CONVERSATION_TYPE.REGULAR,
selfUser,
{
localStore: ConversationProtocol.PROTEUS,
backend: ConversationProtocol.MLS,
},
conversationGroupId,
);

await joinConversationsAfterMigrationFinalisation({
updatedConversations: [updatedConversation],
initialDatabaseConversations: [conversationDatabaseData],
conversations: [mockedConversation],
core: mockCore,
conversationRepository,
});
Expand Down Expand Up @@ -195,21 +182,18 @@ describe('joinConversationsAfterMigrationFinalisation', () => {
const conversationGroupId = 'groupId1';
const selfUser = new User(createUuid());

const {updatedConversation, conversationDatabaseData} = createdMigratedConversationEntities(
const mockedConversations = createConversation(
conversationId,
mockDomain,
ConversationProtocol.PROTEUS,
ConversationProtocol.MLS,
CONVERSATION_TYPE.ONE_TO_ONE,
selfUser,
{
localStore: ConversationProtocol.PROTEUS,
backend: ConversationProtocol.MLS,
},
conversationGroupId,
);

await joinConversationsAfterMigrationFinalisation({
updatedConversations: [updatedConversation],
initialDatabaseConversations: [conversationDatabaseData],
conversations: [mockedConversations],
core: mockCore,
conversationRepository,
});
Expand All @@ -231,57 +215,18 @@ describe('joinConversationsAfterMigrationFinalisation', () => {
const conversationGroupId = 'groupId1';
const selfUser = new User(createUuid());

const {updatedConversation, conversationDatabaseData} = createdMigratedConversationEntities(
conversationId,
mockDomain,
CONVERSATION_TYPE.REGULAR,
selfUser,
{
localStore: ConversationProtocol.MLS,
backend: ConversationProtocol.MLS,
},
conversationGroupId,
);

await joinConversationsAfterMigrationFinalisation({
updatedConversations: [updatedConversation],
initialDatabaseConversations: [conversationDatabaseData],
core: mockCore,
conversationRepository,
});

expect(mockCore.service?.conversation.joinByExternalCommit).not.toHaveBeenCalled();

expect(conversationRepository['eventRepository'].injectEvent).not.toHaveBeenCalled();
});

it('Should not join MLS conversation if conversation was not in the store before', async () => {
const mockCore = container.resolve(Core);
const conversationRepository = await testFactory.exposeConversationActors();

jest.spyOn(mockCore.service!.conversation, 'mlsGroupExistsLocally').mockResolvedValue(false);
jest.spyOn(conversationRepository['eventRepository'], 'injectEvent');

const conversationId = 'conversation1';
const mockDomain = 'anta.wire.link';
const conversationGroupId = 'groupId1';
const selfUser = new User(createUuid());

const {updatedConversation} = createdMigratedConversationEntities(
const mockedConversation = createConversation(
conversationId,
mockDomain,
ConversationProtocol.MLS,
ConversationProtocol.MLS,
CONVERSATION_TYPE.REGULAR,
selfUser,
{
localStore: ConversationProtocol.PROTEUS,
backend: ConversationProtocol.MLS,
},
conversationGroupId,
);

await joinConversationsAfterMigrationFinalisation({
updatedConversations: [updatedConversation],
initialDatabaseConversations: [],
conversations: [mockedConversation],
core: mockCore,
conversationRepository,
});
Expand All @@ -303,21 +248,18 @@ describe('joinConversationsAfterMigrationFinalisation', () => {
const conversationGroupId = 'groupId1';
const selfUser = new User(createUuid());

const {updatedConversation, conversationDatabaseData} = createdMigratedConversationEntities(
const mockedConversation = createConversation(
conversationId,
mockDomain,
ConversationProtocol.PROTEUS,
ConversationProtocol.PROTEUS,
CONVERSATION_TYPE.REGULAR,
selfUser,
{
localStore: ConversationProtocol.PROTEUS,
backend: ConversationProtocol.PROTEUS,
},
conversationGroupId,
);

await joinConversationsAfterMigrationFinalisation({
updatedConversations: [updatedConversation],
initialDatabaseConversations: [conversationDatabaseData],
conversations: [mockedConversation],
core: mockCore,
conversationRepository,
});
Expand Down
Loading

0 comments on commit f0a3c3b

Please sign in to comment.