Skip to content

Commit 86d816f

Browse files
fix: E2EI flow can be interrupted - WPB-23171 πŸ’ (#4397)
Co-authored-by: John Nguyen <28632506+johnxnguyen@users.noreply.github.com>
1 parent 739ed74 commit 86d816f

File tree

18 files changed

+183
-195
lines changed

18 files changed

+183
-195
lines changed

β€Žwire-ios-data-model/Source/MLS/MLSClientManager.swiftβ€Ž

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public protocol MLSClientManagerProtocol {
2525
for qualifiedClientID: QualifiedClientID,
2626
hasRegisteredMLSClient: Bool,
2727
mlsFeature: Feature.MLS,
28-
isBackendMLSEnabled: Bool
28+
isBackendMLSEnabled: Bool,
29+
isE2EIRequired: Bool
2930
) async
3031

3132
}
@@ -53,13 +54,22 @@ public final class MLSClientManager: MLSClientManagerProtocol {
5354
for qualifiedClientID: QualifiedClientID,
5455
hasRegisteredMLSClient: Bool,
5556
mlsFeature: Feature.MLS,
56-
isBackendMLSEnabled: Bool
57+
isBackendMLSEnabled: Bool,
58+
isE2EIRequired: Bool
5759
) async {
5860
guard isBackendMLSEnabled, mlsFeature.isEnabled else {
5961
WireLogger.mls.info("MLS feature in not enabled.")
6062
return
6163
}
6264

65+
if !hasRegisteredMLSClient, isE2EIRequired {
66+
WireLogger.mls.info(
67+
"MLS client needs to be initialized via E2EI.",
68+
attributes: .safePublic
69+
)
70+
return
71+
}
72+
6373
if !hasRegisteredMLSClient {
6474
let mlsClientID = MLSClientID(qualifiedClientID: qualifiedClientID)
6575
await createMLSClient(mlsClientID: mlsClientID)

β€Žwire-ios-data-model/Support/Sourcery/generated/AutoMockable.generated.swiftβ€Ž

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

β€Žwire-ios-data-model/Tests/MLS/MLSClientManagerTests.swiftβ€Ž

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ class MLSClientManagerTests: ZMBaseManagedObjectTest {
9696
for: qualifiedID,
9797
hasRegisteredMLSClient: hasRegisteredMLSClient,
9898
mlsFeature: mlsFeature,
99-
isBackendMLSEnabled: true
99+
isBackendMLSEnabled: true,
100+
isE2EIRequired: false
100101
)
101102

102103
// Then
@@ -147,7 +148,8 @@ class MLSClientManagerTests: ZMBaseManagedObjectTest {
147148
for: qualifiedID,
148149
hasRegisteredMLSClient: hasRegisteredMLSClient,
149150
mlsFeature: mlsFeature,
150-
isBackendMLSEnabled: true
151+
isBackendMLSEnabled: true,
152+
isE2EIRequired: false
151153
)
152154

153155
// Then
@@ -200,7 +202,8 @@ class MLSClientManagerTests: ZMBaseManagedObjectTest {
200202
for: qualifiedID,
201203
hasRegisteredMLSClient: hasRegisteredMLSClient,
202204
mlsFeature: mlsFeature,
203-
isBackendMLSEnabled: true
205+
isBackendMLSEnabled: true,
206+
isE2EIRequired: false
204207
)
205208

206209
// Then
@@ -251,7 +254,8 @@ class MLSClientManagerTests: ZMBaseManagedObjectTest {
251254
for: qualifiedID,
252255
hasRegisteredMLSClient: hasRegisteredMLSClient,
253256
mlsFeature: mlsFeature,
254-
isBackendMLSEnabled: false
257+
isBackendMLSEnabled: false,
258+
isE2EIRequired: false
255259
)
256260

257261
// Then

β€Žwire-ios-request-strategy/Sources/Request Strategies/Feature configurations/Payload/FeatureConfigsPayloadProcessor.swiftβ€Ž

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -210,109 +210,4 @@ struct FeatureConfigsPayloadProcessor {
210210
}
211211
}
212212

213-
func processEventPayload(
214-
data: Data,
215-
featureName: Feature.Name,
216-
repository: LegacyFeatureRepositoryInterface,
217-
mlsClientManager: MLSClientManagerProtocol,
218-
in context: NSManagedObjectContext
219-
) throws {
220-
switch featureName {
221-
case .conferenceCalling:
222-
if let apiVersion, apiVersion >= .v6 {
223-
let response = try decoder.decode(
224-
FeatureStatusWithConfig<Feature.ConferenceCalling.Config>.self,
225-
from: data
226-
)
227-
repository.storeConferenceCalling(.init(status: response.status, config: response.config))
228-
} else {
229-
let response = try decoder.decode(FeatureStatus.self, from: data)
230-
repository.storeConferenceCalling(.init(status: response.status))
231-
}
232-
233-
case .fileSharing:
234-
let response = try decoder.decode(FeatureStatus.self, from: data)
235-
repository.storeFileSharing(.init(status: response.status))
236-
237-
case .appLock:
238-
let response = try decoder.decode(FeatureStatusWithConfig<Feature.AppLock.Config>.self, from: data)
239-
repository.storeAppLock(.init(status: response.status, config: response.config))
240-
241-
case .apps:
242-
let response = try decoder.decode(FeatureStatus.self, from: data)
243-
repository.storeApps(.init(status: response.status))
244-
245-
case .selfDeletingMessages:
246-
let response = try decoder.decode(
247-
FeatureStatusWithConfig<Feature.SelfDeletingMessages.Config>.self,
248-
from: data
249-
)
250-
repository.storeSelfDeletingMessages(.init(status: response.status, config: response.config))
251-
252-
case .conversationGuestLinks:
253-
let response = try decoder.decode(FeatureStatus.self, from: data)
254-
repository.storeConversationGuestLinks(.init(status: response.status))
255-
256-
case .classifiedDomains:
257-
let response = try decoder.decode(
258-
FeatureStatusWithConfig<Feature.ClassifiedDomains.Config>.self,
259-
from: data
260-
)
261-
repository.storeClassifiedDomains(.init(status: response.status, config: response.config))
262-
263-
case .digitalSignature:
264-
let response = try decoder.decode(FeatureStatus.self, from: data)
265-
repository.storeDigitalSignature(.init(status: response.status))
266-
267-
case .mls:
268-
let response = try decoder.decode(FeatureStatusWithConfig<Feature.MLS.Config>.self, from: data)
269-
repository.storeMLS(.init(status: response.status, config: response.config))
270-
Task {
271-
let mlsFeature = await repository.fetchMLS()
272-
await processMLSFeatureConfigChanges(
273-
mlsClientManager: mlsClientManager,
274-
context: context,
275-
mlsFeature: mlsFeature
276-
)
277-
}
278-
279-
case .mlsMigration:
280-
let response = try decoder.decode(FeatureStatusWithConfig<Feature.MLSMigration.Config>.self, from: data)
281-
repository.storeMLSMigration(.init(status: response.status, config: response.config))
282-
283-
case .e2ei:
284-
let response = try decoder.decode(FeatureStatusWithConfig<Feature.E2EI.Config>.self, from: data)
285-
repository.storeE2EI(.init(status: response.status, config: response.config))
286-
287-
case .channels, .consumableNotifications, .allowedGlobalOperations, .cells, .assetAuditLog, .cellsInternal,
288-
.simplifiedUserConnectionRequestQRCode:
289-
WireLogger.featureConfigs.warn(
290-
"decoding unsupported feature config: \"\(featureName)\", this should not happen",
291-
attributes: .safePublic
292-
)
293-
}
294-
}
295-
296-
private func processMLSFeatureConfigChanges(
297-
mlsClientManager: MLSClientManagerProtocol,
298-
context: NSManagedObjectContext,
299-
mlsFeature: Feature.MLS
300-
) async {
301-
let (qualifiedSelfClientID, hasRegisteredMLSClient) = await context.perform {
302-
let selfClient = ZMUser.selfUser(in: context).selfClient()
303-
return (selfClient?.qualifiedClientID, selfClient?.hasRegisteredMLSClient ?? false)
304-
}
305-
306-
guard let qualifiedSelfClientID else {
307-
WireLogger.mls.warn("`qualifiedClientID` is missing for selfClient")
308-
return
309-
}
310-
await mlsClientManager.initializeMLSClientIfNeeded(
311-
for: qualifiedSelfClientID,
312-
hasRegisteredMLSClient: hasRegisteredMLSClient,
313-
mlsFeature: mlsFeature,
314-
isBackendMLSEnabled: BackendInfo.isMLSEnabled
315-
)
316-
}
317-
318213
}

β€Žwire-ios-sync-engine/Source/SessionManager/SessionManager+UserSessionLogoutDelegate.swiftβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ extension SessionManager: UserSessionLogoutDelegate {
7171
let environment = try? environmentStore.fetchBackendEnvironment(accountID: accountId)
7272

7373
delegate?.sessionManagerWillLogout(
74+
accountID: accountId,
7475
environment: environment,
7576
error: error,
7677
userSessionCanBeTornDown: nil

β€Žwire-ios-sync-engine/Source/SessionManager/SessionManager+UserSessionSelfUserClientDelegate.swiftβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ extension SessionManager: UserSessionSelfUserClientDelegate {
6464
let environment = try? environmentStore.fetchBackendEnvironment(accountID: accountId)
6565

6666
delegate?.sessionManagerWillLogout(
67+
accountID: accountId,
6768
environment: environment,
6869
error: error,
6970
userSessionCanBeTornDown: nil

β€Žwire-ios-sync-engine/Source/SessionManager/SessionManager.swiftβ€Ž

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public protocol SessionActivationObserver: AnyObject {
7171
// sourcery: AutoMockable
7272
public protocol SessionManagerDelegate: AnyObject, SessionActivationObserver {
7373
func sessionManagerWillLogout(
74+
accountID: UUID?,
7475
environment: BackendEnvironment2?,
7576
error: Error?,
7677
userSessionCanBeTornDown: (() -> Void)?
@@ -647,6 +648,7 @@ public final class SessionManager: NSObject, SessionManagerType {
647648
} else {
648649
createUnauthenticatedSession()
649650
delegate?.sessionManagerWillLogout(
651+
accountID: nil,
650652
environment: nil,
651653
error: nil,
652654
userSessionCanBeTornDown: nil
@@ -753,6 +755,7 @@ public final class SessionManager: NSObject, SessionManagerType {
753755
guard isConfirmed else { return }
754756
let error = NSError(userSessionErrorCode: .addAccountRequested, userInfo: userInfo)
755757
self?.delegate?.sessionManagerWillLogout(
758+
accountID: nil,
756759
environment: nil,
757760
error: error
758761
) { [weak self] in
@@ -866,6 +869,7 @@ public final class SessionManager: NSObject, SessionManagerType {
866869
guard let activeUserSession else {
867870
WireLogger.sessionManager.critical("No active user session")
868871
delegate?.sessionManagerWillLogout(
872+
accountID: nil,
869873
environment: nil,
870874
error: error,
871875
userSessionCanBeTornDown: nil
@@ -883,6 +887,7 @@ public final class SessionManager: NSObject, SessionManagerType {
883887
let environment = try? environmentStore.fetchBackendEnvironment(accountID: account.userIdentifier)
884888

885889
delegate?.sessionManagerWillLogout(
890+
accountID: account.userIdentifier,
886891
environment: environment,
887892
error: error
888893
) { [weak self] in
@@ -918,6 +923,7 @@ public final class SessionManager: NSObject, SessionManagerType {
918923
let environment = try? environmentStore.fetchBackendEnvironment(accountID: account.userIdentifier)
919924

920925
delegate?.sessionManagerWillLogout(
926+
accountID: account.userIdentifier,
921927
environment: environment,
922928
error: error,
923929
userSessionCanBeTornDown: nil
@@ -953,9 +959,9 @@ public final class SessionManager: NSObject, SessionManagerType {
953959
// If the user isn't logged in it's because they still need
954960
// to complete the login flow, which will be handle elsewhere.
955961
if session.isLoggedIn {
962+
await session.triggerSync()
956963
delegate?.sessionManagerDidReportLockChange(forSession: session)
957964
performPostUnlockActionsIfPossible(for: session)
958-
959965
await configureAnalytics(for: session)
960966
await requestCertificateEnrollmentIfNeeded()
961967
} else {
@@ -1027,6 +1033,9 @@ public final class SessionManager: NSObject, SessionManagerType {
10271033
newSession: userSession,
10281034
coreDataStack: userSession.coreDataStack
10291035
)
1036+
1037+
await userSession.start()
1038+
10301039
return userSession
10311040

10321041
} catch UserSessionLoader.Failure.buildIsBlacklisted {
@@ -1601,6 +1610,14 @@ extension SessionManager: UnauthenticatedSessionDelegate {
16011610
return
16021611
}
16031612

1613+
// The journal may have old values for the same user
1614+
// from a previous installation or login session.
1615+
var journal = Journal(
1616+
userID: account.userIdentifier,
1617+
storage: sharedUserDefaults
1618+
)
1619+
journal[.isInitialSyncRequired] = true
1620+
16041621
accountManager.addAndSelect(account)
16051622

16061623
Task { @MainActor in

β€Žwire-ios-sync-engine/Source/SessionManager/UserSessionLoader.swiftβ€Ž

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,13 @@ final class UserSessionLoader {
196196
}
197197

198198
// Check if this backend supports MLS.
199-
let isBackendMLSEnabled = try await isBackendMLSEnabled(
199+
if let isBackendMLSEnabled = try await isBackendMLSEnabled(
200200
networkService: networkServices.rest,
201201
cookieStorage: cookieStorage,
202202
apiVersion: metadata.apiVersion
203-
)
204-
journal[.isBackendMLSEnabled] = isBackendMLSEnabled
203+
) {
204+
journal[.isBackendMLSEnabled] = isBackendMLSEnabled
205+
}
205206

206207
// Create user session.
207208
let userSession = await createUserSession(
@@ -593,7 +594,7 @@ final class UserSessionLoader {
593594
networkService: NetworkService,
594595
cookieStorage: CookieStorage,
595596
apiVersion: WireNetwork.APIVersion
596-
) async throws -> Bool {
597+
) async throws -> Bool? {
597598
do {
598599
let authenticationManager = AuthenticationManager(
599600
clientID: nil,
@@ -614,7 +615,7 @@ final class UserSessionLoader {
614615
MLSAPIError.unsupportedEndpointForAPIVersion,
615616
MLSAPIError.mlsNotEnabled {
616617
// Don't block session loading, we'll try again later.
617-
return false
618+
return nil
618619
}
619620
}
620621

@@ -665,21 +666,15 @@ final class UserSessionLoader {
665666
}
666667

667668
// Perform consumable notifications migration.
668-
var shouldTriggerSync = true
669669
do {
670670
try await userSession.migrateToConsumableNotificationsIfNeeded()
671671
} catch ZMUserSessionError.selfClientNotReady {
672672
// We skip trigger sync, because in this case (fresh login),
673673
// we don't have a registered client yet, so no consumable capability
674674
WireLogger.sync.warn("No consumable-notifications migrator available")
675-
shouldTriggerSync = false
676675
} catch {
677676
throw Failure.failedToMigrationToConsumableNotifications(error)
678677
}
679-
680-
if shouldTriggerSync {
681-
await userSession.triggerSync()
682-
}
683678
}
684679

685680
enum Failure: Error, SafeForLoggingStringConvertible {

β€Žwire-ios-sync-engine/Source/Synchronization/ZMOperationLoop.hβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
apiVersion:(nullable NSNumber *)apiVersion;
5050

5151
- (void)tearDown;
52+
- (void)resumeEnqueuing;
5253

5354
@end
5455

β€Žwire-ios-sync-engine/Source/Synchronization/ZMOperationLoop.mβ€Ž

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ - (instancetype)initWithTransportSession:(id<TransportSessionType>)transportSess
7070
self.transportSession = transportSession;
7171
self.requestStrategy = requestStrategy;
7272
self.syncMOC = syncMOC;
73-
self.shouldStopEnqueueing = NO;
73+
self.shouldStopEnqueueing = YES;
7474
self.operationStatus.delegate = self;
7575
self.isDeveloperModeEnabled = isDeveloperModeEnabled;
7676
self.isSyncV2Enabled = isSyncV2Enabled;
@@ -171,6 +171,12 @@ - (void)executeNextOperation
171171
}];
172172
}
173173

174+
- (void)resumeEnqueuing
175+
{
176+
self.shouldStopEnqueueing = NO;
177+
[self newRequestsAvailable];
178+
}
179+
174180
@end
175181

176182

0 commit comments

Comments
Β (0)