Skip to content

Commit 724a88c

Browse files
committed
feat: add Kalium-backed iOS login probe
1 parent 4f77230 commit 724a88c

14 files changed

Lines changed: 1206 additions & 26 deletions

File tree

kalium

Submodule kalium updated 48 files

shared/export-ios/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ kotlin {
1212
val commonMain by getting {
1313
dependencies {
1414
api(libs.coroutines.core)
15+
implementation("com.wire.kalium:kalium-logic")
1516
}
1617
}
1718

shared/export-ios/src/commonMain/kotlin/com/wire/ios/shared/WireIosSharedConfig.kt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,46 @@ import com.wire.ios.shared.auth.login.model.LoginServerLinks
2121

2222
data class WireIosSharedConfig(
2323
val defaultServerLinks: LoginServerLinks,
24+
val runtimeConfig: IosKaliumRuntimeConfig? = null,
2425
val isThereActiveSession: Boolean = false,
2526
val maxAccountsReached: Boolean = false,
2627
val nomadAccountBlocksLogin: Boolean = false,
2728
val isAccountCreationAllowed: Boolean = true,
2829
val useNewRegistration: Boolean = true,
2930
)
3031

32+
data class IosKaliumRuntimeConfig(
33+
val appGroupRootPath: String,
34+
val accountDataPath: String? = null,
35+
val sqlDelightRootPath: String,
36+
val coreCryptoPath: String? = null,
37+
val userId: String? = null,
38+
val clientId: String? = null,
39+
val backendDomain: String,
40+
val serverLinks: LoginServerLinks,
41+
val migrationMode: MigrationMode,
42+
)
43+
44+
enum class MigrationMode {
45+
CleanInstallProbe,
46+
ExistingIosAccountOpenInPlace,
47+
}
48+
3149
fun createWireIosSharedConfig(defaultServerLinks: LoginServerLinks): WireIosSharedConfig =
3250
WireIosSharedConfig(defaultServerLinks = defaultServerLinks)
3351

3452
fun createWireIosSharedConfig(
3553
defaultServerLinks: LoginServerLinks,
54+
runtimeConfig: IosKaliumRuntimeConfig?,
55+
): WireIosSharedConfig =
56+
WireIosSharedConfig(
57+
defaultServerLinks = defaultServerLinks,
58+
runtimeConfig = runtimeConfig,
59+
)
60+
61+
fun createWireIosSharedConfig(
62+
defaultServerLinks: LoginServerLinks,
63+
runtimeConfig: IosKaliumRuntimeConfig?,
3664
isThereActiveSession: Boolean,
3765
maxAccountsReached: Boolean,
3866
nomadAccountBlocksLogin: Boolean,
@@ -41,9 +69,48 @@ fun createWireIosSharedConfig(
4169
): WireIosSharedConfig =
4270
WireIosSharedConfig(
4371
defaultServerLinks = defaultServerLinks,
72+
runtimeConfig = runtimeConfig,
4473
isThereActiveSession = isThereActiveSession,
4574
maxAccountsReached = maxAccountsReached,
4675
nomadAccountBlocksLogin = nomadAccountBlocksLogin,
4776
isAccountCreationAllowed = isAccountCreationAllowed,
4877
useNewRegistration = useNewRegistration,
4978
)
79+
80+
fun createIosKaliumRuntimeConfig(
81+
appGroupRootPath: String,
82+
sqlDelightRootPath: String,
83+
backendDomain: String,
84+
serverLinks: LoginServerLinks,
85+
migrationMode: MigrationMode,
86+
): IosKaliumRuntimeConfig =
87+
IosKaliumRuntimeConfig(
88+
appGroupRootPath = appGroupRootPath,
89+
sqlDelightRootPath = sqlDelightRootPath,
90+
backendDomain = backendDomain,
91+
serverLinks = serverLinks,
92+
migrationMode = migrationMode,
93+
)
94+
95+
fun createIosKaliumRuntimeConfig(
96+
appGroupRootPath: String,
97+
accountDataPath: String?,
98+
sqlDelightRootPath: String,
99+
coreCryptoPath: String?,
100+
userId: String?,
101+
clientId: String?,
102+
backendDomain: String,
103+
serverLinks: LoginServerLinks,
104+
migrationMode: MigrationMode,
105+
): IosKaliumRuntimeConfig =
106+
IosKaliumRuntimeConfig(
107+
appGroupRootPath = appGroupRootPath,
108+
accountDataPath = accountDataPath,
109+
sqlDelightRootPath = sqlDelightRootPath,
110+
coreCryptoPath = coreCryptoPath,
111+
userId = userId,
112+
clientId = clientId,
113+
backendDomain = backendDomain,
114+
serverLinks = serverLinks,
115+
migrationMode = migrationMode,
116+
)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2026 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*/
18+
package com.wire.ios.shared.auth.email
19+
20+
interface LoginEmailBackend {
21+
suspend fun login(
22+
userIdentifier: String,
23+
password: String,
24+
secondFactorVerificationCode: String?,
25+
usernameAllowed: Boolean,
26+
): LoginEmailBackendResult
27+
28+
suspend fun requestSecondFactorCode(userIdentifier: String): LoginEmailBackendResult
29+
}
30+
31+
sealed interface LoginEmailBackendResult {
32+
data class Success(
33+
val initialSyncCompleted: Boolean,
34+
val isE2EIRequired: Boolean,
35+
) : LoginEmailBackendResult
36+
37+
data class SecondFactorRequired(
38+
val email: String,
39+
val isCurrentCodeInvalid: Boolean = false,
40+
) : LoginEmailBackendResult
41+
42+
data object RemoveDeviceNeeded : LoginEmailBackendResult
43+
data class Failure(val error: LoginEmailError) : LoginEmailBackendResult
44+
}
45+
46+
class LocalLoginEmailBackend : LoginEmailBackend {
47+
override suspend fun login(
48+
userIdentifier: String,
49+
password: String,
50+
secondFactorVerificationCode: String?,
51+
usernameAllowed: Boolean,
52+
): LoginEmailBackendResult =
53+
LoginEmailBackendResult.Success(
54+
initialSyncCompleted = false,
55+
isE2EIRequired = false,
56+
)
57+
58+
override suspend fun requestSecondFactorCode(userIdentifier: String): LoginEmailBackendResult =
59+
LoginEmailBackendResult.SecondFactorRequired(email = userIdentifier)
60+
}

shared/export-ios/src/commonMain/kotlin/com/wire/ios/shared/auth/email/LoginEmailContract.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ sealed interface LoginEmailIntent {
8080
data object ResendSecondFactorCode : LoginEmailIntent
8181
}
8282

83+
/**
84+
* One-shot login actions for Swift hosts.
85+
*
86+
* Invalid credentials intentionally do not emit an effect. They are represented only through
87+
* [LoginEmailFlowState.Error] with [LoginEmailError.InvalidCredentials].
88+
*/
8389
sealed interface LoginEmailEffect {
8490
data class LoginSucceeded(
8591
val initialSyncCompleted: Boolean,

0 commit comments

Comments
 (0)