mirror of
https://github.com/bitwarden/android.git
synced 2025-02-03 21:51:03 +03:00
PM-13803 Check to see if an existing admin request is pending before … (#4271)
This commit is contained in:
parent
1bb85d0fa0
commit
6dd783051f
8 changed files with 219 additions and 42 deletions
|
@ -7,13 +7,21 @@ import kotlinx.serialization.Serializable
|
||||||
* Container for the user's API tokens.
|
* Container for the user's API tokens.
|
||||||
*
|
*
|
||||||
* @property requestId The ID of the pending Auth Request.
|
* @property requestId The ID of the pending Auth Request.
|
||||||
* @property requestPrivateKey The private of the pending Auth Request.
|
* @property requestPrivateKey The private key of the pending Auth Request.
|
||||||
|
* @property requestAccessCode The access code of the pending Auth Request.
|
||||||
|
* @property requestFingerprint The fingerprint of the pending Auth Request.
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PendingAuthRequestJson(
|
data class PendingAuthRequestJson(
|
||||||
@SerialName("Id")
|
@SerialName("id")
|
||||||
val requestId: String,
|
val requestId: String,
|
||||||
|
|
||||||
@SerialName("PrivateKey")
|
@SerialName("privateKey")
|
||||||
val requestPrivateKey: String,
|
val requestPrivateKey: String,
|
||||||
|
|
||||||
|
@SerialName("accessCode")
|
||||||
|
val requestAccessCode: String,
|
||||||
|
|
||||||
|
@SerialName("fingerprint")
|
||||||
|
val requestFingerprint: String,
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,6 +17,7 @@ import com.x8bit.bitwarden.data.auth.manager.model.CreateAuthRequestResult
|
||||||
import com.x8bit.bitwarden.data.auth.manager.util.isSso
|
import com.x8bit.bitwarden.data.auth.manager.util.isSso
|
||||||
import com.x8bit.bitwarden.data.auth.manager.util.toAuthRequestTypeJson
|
import com.x8bit.bitwarden.data.auth.manager.util.toAuthRequestTypeJson
|
||||||
import com.x8bit.bitwarden.data.platform.util.asFailure
|
import com.x8bit.bitwarden.data.platform.util.asFailure
|
||||||
|
import com.x8bit.bitwarden.data.platform.util.asSuccess
|
||||||
import com.x8bit.bitwarden.data.platform.util.flatMap
|
import com.x8bit.bitwarden.data.platform.util.flatMap
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||||
import kotlinx.coroutines.currentCoroutineContext
|
import kotlinx.coroutines.currentCoroutineContext
|
||||||
|
@ -65,7 +66,7 @@ class AuthRequestManagerImpl(
|
||||||
email: String,
|
email: String,
|
||||||
authRequestType: AuthRequestType,
|
authRequestType: AuthRequestType,
|
||||||
): Flow<CreateAuthRequestResult> = flow {
|
): Flow<CreateAuthRequestResult> = flow {
|
||||||
val initialResult = createNewAuthRequest(
|
val initialResult = createNewAuthRequestIfNecessary(
|
||||||
email = email,
|
email = email,
|
||||||
authRequestType = authRequestType.toAuthRequestTypeJson(),
|
authRequestType = authRequestType.toAuthRequestTypeJson(),
|
||||||
)
|
)
|
||||||
|
@ -74,7 +75,6 @@ class AuthRequestManagerImpl(
|
||||||
emit(CreateAuthRequestResult.Error)
|
emit(CreateAuthRequestResult.Error)
|
||||||
return@flow
|
return@flow
|
||||||
}
|
}
|
||||||
val authRequestResponse = initialResult.authRequestResponse
|
|
||||||
var authRequest = initialResult.authRequest
|
var authRequest = initialResult.authRequest
|
||||||
emit(CreateAuthRequestResult.Update(authRequest))
|
emit(CreateAuthRequestResult.Update(authRequest))
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ class AuthRequestManagerImpl(
|
||||||
newAuthRequestService
|
newAuthRequestService
|
||||||
.getAuthRequestUpdate(
|
.getAuthRequestUpdate(
|
||||||
requestId = authRequest.id,
|
requestId = authRequest.id,
|
||||||
accessCode = authRequestResponse.accessCode,
|
accessCode = initialResult.accessCode,
|
||||||
isSso = authRequestType.isSso,
|
isSso = authRequestType.isSso,
|
||||||
)
|
)
|
||||||
.map { request ->
|
.map { request ->
|
||||||
|
@ -112,7 +112,8 @@ class AuthRequestManagerImpl(
|
||||||
emit(
|
emit(
|
||||||
CreateAuthRequestResult.Success(
|
CreateAuthRequestResult.Success(
|
||||||
authRequest = updateAuthRequest,
|
authRequest = updateAuthRequest,
|
||||||
authRequestResponse = authRequestResponse,
|
privateKey = initialResult.privateKey,
|
||||||
|
accessCode = initialResult.accessCode,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -354,6 +355,52 @@ class AuthRequestManagerImpl(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new auth request for the given email and returns a [NewAuthRequestData].
|
||||||
|
* If the auth request type is [AuthRequestTypeJson.ADMIN_APPROVAL], check for a
|
||||||
|
* pending auth request and return it if it exists we should return that request.
|
||||||
|
*/
|
||||||
|
private suspend fun createNewAuthRequestIfNecessary(
|
||||||
|
email: String,
|
||||||
|
authRequestType: AuthRequestTypeJson,
|
||||||
|
): Result<NewAuthRequestData> {
|
||||||
|
return if (authRequestType == AuthRequestTypeJson.ADMIN_APPROVAL) {
|
||||||
|
authDiskSource
|
||||||
|
.getPendingAuthRequest(requireNotNull(activeUserId))
|
||||||
|
?.let { pendingAuthRequest ->
|
||||||
|
authRequestsService
|
||||||
|
.getAuthRequest(pendingAuthRequest.requestId)
|
||||||
|
.map {
|
||||||
|
NewAuthRequestData(
|
||||||
|
authRequest = AuthRequest(
|
||||||
|
id = it.id,
|
||||||
|
publicKey = it.publicKey,
|
||||||
|
platform = it.platform,
|
||||||
|
ipAddress = it.ipAddress,
|
||||||
|
key = it.key,
|
||||||
|
masterPasswordHash = it.masterPasswordHash,
|
||||||
|
creationDate = it.creationDate,
|
||||||
|
responseDate = it.responseDate,
|
||||||
|
requestApproved = it.requestApproved ?: false,
|
||||||
|
originUrl = it.originUrl,
|
||||||
|
fingerprint = pendingAuthRequest.requestFingerprint,
|
||||||
|
),
|
||||||
|
privateKey = pendingAuthRequest.requestPrivateKey,
|
||||||
|
accessCode = pendingAuthRequest.requestAccessCode,
|
||||||
|
)
|
||||||
|
.asSuccess()
|
||||||
|
}
|
||||||
|
.getOrNull()
|
||||||
|
}
|
||||||
|
?: createNewAuthRequest(email = email, authRequestType = authRequestType)
|
||||||
|
} else {
|
||||||
|
createNewAuthRequest(
|
||||||
|
email = email,
|
||||||
|
authRequestType = authRequestType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to create a new auth request for the given email and returns a [NewAuthRequestData]
|
* Attempts to create a new auth request for the given email and returns a [NewAuthRequestData]
|
||||||
* with the [AuthRequest] and [AuthRequestResponse].
|
* with the [AuthRequest] and [AuthRequestResponse].
|
||||||
|
@ -381,6 +428,8 @@ class AuthRequestManagerImpl(
|
||||||
pendingAuthRequest = PendingAuthRequestJson(
|
pendingAuthRequest = PendingAuthRequestJson(
|
||||||
requestId = it.id,
|
requestId = it.id,
|
||||||
requestPrivateKey = authRequestResponse.privateKey,
|
requestPrivateKey = authRequestResponse.privateKey,
|
||||||
|
requestAccessCode = authRequestResponse.accessCode,
|
||||||
|
requestFingerprint = authRequestResponse.fingerprint,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -400,7 +449,13 @@ class AuthRequestManagerImpl(
|
||||||
fingerprint = authRequestResponse.fingerprint,
|
fingerprint = authRequestResponse.fingerprint,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.map { NewAuthRequestData(it, authRequestResponse) }
|
.map {
|
||||||
|
NewAuthRequestData(
|
||||||
|
authRequest = it,
|
||||||
|
privateKey = authRequestResponse.privateKey,
|
||||||
|
accessCode = authRequestResponse.accessCode,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getFingerprintPhrase(
|
private suspend fun getFingerprintPhrase(
|
||||||
|
@ -420,5 +475,6 @@ class AuthRequestManagerImpl(
|
||||||
*/
|
*/
|
||||||
private data class NewAuthRequestData(
|
private data class NewAuthRequestData(
|
||||||
val authRequest: AuthRequest,
|
val authRequest: AuthRequest,
|
||||||
val authRequestResponse: AuthRequestResponse,
|
val privateKey: String,
|
||||||
|
val accessCode: String,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.x8bit.bitwarden.data.auth.manager.model
|
package com.x8bit.bitwarden.data.auth.manager.model
|
||||||
|
|
||||||
import com.bitwarden.core.AuthRequestResponse
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Models result of creating a new login approval request.
|
* Models result of creating a new login approval request.
|
||||||
*/
|
*/
|
||||||
|
@ -18,7 +16,8 @@ sealed class CreateAuthRequestResult {
|
||||||
*/
|
*/
|
||||||
data class Success(
|
data class Success(
|
||||||
val authRequest: AuthRequest,
|
val authRequest: AuthRequest,
|
||||||
val authRequestResponse: AuthRequestResponse,
|
val privateKey: String,
|
||||||
|
val accessCode: String,
|
||||||
) : CreateAuthRequestResult()
|
) : CreateAuthRequestResult()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -116,11 +116,11 @@ class LoginWithDeviceViewModel @Inject constructor(
|
||||||
),
|
),
|
||||||
dialogState = null,
|
dialogState = null,
|
||||||
loginData = LoginWithDeviceState.LoginData(
|
loginData = LoginWithDeviceState.LoginData(
|
||||||
accessCode = result.authRequestResponse.accessCode,
|
accessCode = result.accessCode,
|
||||||
requestId = result.authRequest.id,
|
requestId = result.authRequest.id,
|
||||||
masterPasswordHash = result.authRequest.masterPasswordHash,
|
masterPasswordHash = result.authRequest.masterPasswordHash,
|
||||||
asymmetricalKey = requireNotNull(result.authRequest.key),
|
asymmetricalKey = requireNotNull(result.authRequest.key),
|
||||||
privateKey = result.authRequestResponse.privateKey,
|
privateKey = result.privateKey,
|
||||||
captchaToken = null,
|
captchaToken = null,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -244,6 +244,8 @@ class AuthDiskSourceTest {
|
||||||
val pendingAuthRequestJson = PendingAuthRequestJson(
|
val pendingAuthRequestJson = PendingAuthRequestJson(
|
||||||
requestId = "12345",
|
requestId = "12345",
|
||||||
requestPrivateKey = "67890",
|
requestPrivateKey = "67890",
|
||||||
|
requestFingerprint = "fingerprint",
|
||||||
|
requestAccessCode = "accessCode",
|
||||||
)
|
)
|
||||||
authDiskSource.storePendingAuthRequest(
|
authDiskSource.storePendingAuthRequest(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
|
@ -594,15 +596,22 @@ class AuthDiskSourceTest {
|
||||||
pendingAdminAuthRequestKey,
|
pendingAdminAuthRequestKey,
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"Id": "12345",
|
"id": "12345",
|
||||||
"PrivateKey": "67890"
|
"privateKey": "67890",
|
||||||
|
"fingerprint": "fingerprint",
|
||||||
|
"accessCode": "accessCode"
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val actual = authDiskSource.getPendingAuthRequest(userId = mockUserId)
|
val actual = authDiskSource.getPendingAuthRequest(userId = mockUserId)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
PendingAuthRequestJson(requestId = "12345", requestPrivateKey = "67890"),
|
PendingAuthRequestJson(
|
||||||
|
requestId = "12345",
|
||||||
|
requestPrivateKey = "67890",
|
||||||
|
requestFingerprint = "fingerprint",
|
||||||
|
requestAccessCode = "accessCode",
|
||||||
|
),
|
||||||
actual,
|
actual,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -615,6 +624,8 @@ class AuthDiskSourceTest {
|
||||||
val pendingAdminAuthRequest = PendingAuthRequestJson(
|
val pendingAdminAuthRequest = PendingAuthRequestJson(
|
||||||
requestId = "12345",
|
requestId = "12345",
|
||||||
requestPrivateKey = "67890",
|
requestPrivateKey = "67890",
|
||||||
|
requestFingerprint = "fingerprint",
|
||||||
|
requestAccessCode = "accessCode",
|
||||||
)
|
)
|
||||||
authDiskSource.storePendingAuthRequest(
|
authDiskSource.storePendingAuthRequest(
|
||||||
userId = mockUserId,
|
userId = mockUserId,
|
||||||
|
@ -628,8 +639,10 @@ class AuthDiskSourceTest {
|
||||||
json.parseToJsonElement(
|
json.parseToJsonElement(
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"Id": "12345",
|
"id": "12345",
|
||||||
"PrivateKey": "67890"
|
"privateKey": "67890",
|
||||||
|
"fingerprint": "fingerprint",
|
||||||
|
"accessCode": "accessCode"
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.trimIndent(),
|
.trimIndent(),
|
||||||
|
|
|
@ -162,7 +162,8 @@ class AuthRequestManagerTest {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
CreateAuthRequestResult.Success(
|
CreateAuthRequestResult.Success(
|
||||||
authRequest = authRequest.copy(requestApproved = true),
|
authRequest = authRequest.copy(requestApproved = true),
|
||||||
authRequestResponse = authRequestResponse,
|
privateKey = authRequestResponse.privateKey,
|
||||||
|
accessCode = authRequestResponse.accessCode,
|
||||||
),
|
),
|
||||||
awaitItem(),
|
awaitItem(),
|
||||||
)
|
)
|
||||||
|
@ -170,6 +171,87 @@ class AuthRequestManagerTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
@Test
|
||||||
|
fun `createAuthRequestWithUpdates with a pending admin request Success and getAuthRequestUpdate with approval should emit Success`() =
|
||||||
|
runTest {
|
||||||
|
val email = "email@email.com"
|
||||||
|
val authRequestResponse = AUTH_REQUEST_RESPONSE
|
||||||
|
val authRequestResponseJson = AuthRequestsResponseJson.AuthRequest(
|
||||||
|
id = "1",
|
||||||
|
publicKey = PUBLIC_KEY,
|
||||||
|
platform = "Android",
|
||||||
|
ipAddress = "192.168.0.1",
|
||||||
|
key = "public",
|
||||||
|
masterPasswordHash = "verySecureHash",
|
||||||
|
creationDate = ZonedDateTime.parse("2024-09-13T00:00Z"),
|
||||||
|
responseDate = null,
|
||||||
|
requestApproved = false,
|
||||||
|
originUrl = "www.bitwarden.com",
|
||||||
|
)
|
||||||
|
fakeAuthDiskSource.userState = SINGLE_USER_STATE
|
||||||
|
fakeAuthDiskSource.storePendingAuthRequest(
|
||||||
|
userId = USER_ID,
|
||||||
|
pendingAuthRequest = PendingAuthRequestJson(
|
||||||
|
requestId = authRequestResponseJson.id,
|
||||||
|
requestPrivateKey = authRequestResponse.privateKey,
|
||||||
|
requestAccessCode = authRequestResponse.accessCode,
|
||||||
|
requestFingerprint = authRequestResponse.fingerprint,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val updatedAuthRequestResponseJson = authRequestResponseJson.copy(
|
||||||
|
requestApproved = true,
|
||||||
|
)
|
||||||
|
val authRequest = AuthRequest(
|
||||||
|
id = authRequestResponseJson.id,
|
||||||
|
publicKey = authRequestResponseJson.publicKey,
|
||||||
|
platform = authRequestResponseJson.platform,
|
||||||
|
ipAddress = authRequestResponseJson.ipAddress,
|
||||||
|
key = authRequestResponseJson.key,
|
||||||
|
masterPasswordHash = authRequestResponseJson.masterPasswordHash,
|
||||||
|
creationDate = authRequestResponseJson.creationDate,
|
||||||
|
responseDate = authRequestResponseJson.responseDate,
|
||||||
|
requestApproved = authRequestResponseJson.requestApproved ?: false,
|
||||||
|
originUrl = authRequestResponseJson.originUrl,
|
||||||
|
fingerprint = authRequestResponse.fingerprint,
|
||||||
|
)
|
||||||
|
coEvery {
|
||||||
|
authRequestsService.getAuthRequest(
|
||||||
|
requestId = authRequest.id,
|
||||||
|
)
|
||||||
|
} returns authRequestResponseJson.asSuccess()
|
||||||
|
coEvery {
|
||||||
|
newAuthRequestService.getAuthRequestUpdate(
|
||||||
|
requestId = authRequest.id,
|
||||||
|
accessCode = authRequestResponse.accessCode,
|
||||||
|
isSso = true,
|
||||||
|
)
|
||||||
|
} returnsMany listOf(
|
||||||
|
authRequestResponseJson.asSuccess(),
|
||||||
|
updatedAuthRequestResponseJson.asSuccess(),
|
||||||
|
)
|
||||||
|
|
||||||
|
repository
|
||||||
|
.createAuthRequestWithUpdates(
|
||||||
|
email = email,
|
||||||
|
authRequestType = AuthRequestType.SSO_ADMIN_APPROVAL,
|
||||||
|
)
|
||||||
|
.test {
|
||||||
|
assertEquals(CreateAuthRequestResult.Update(authRequest), awaitItem())
|
||||||
|
assertEquals(CreateAuthRequestResult.Update(authRequest), awaitItem())
|
||||||
|
assertEquals(
|
||||||
|
CreateAuthRequestResult.Success(
|
||||||
|
authRequest = authRequest.copy(requestApproved = true),
|
||||||
|
privateKey = authRequestResponse.privateKey,
|
||||||
|
accessCode = authRequestResponse.accessCode,
|
||||||
|
),
|
||||||
|
awaitItem(),
|
||||||
|
)
|
||||||
|
awaitComplete()
|
||||||
|
}
|
||||||
|
coVerify(exactly = 0) { authSdkSource.getNewAuthRequest(any()) }
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
@Suppress("MaxLineLength")
|
||||||
@Test
|
@Test
|
||||||
fun `createAuthRequestWithUpdates with createNewAuthRequest Success and getAuthRequestUpdate with response date and no approval should emit Declined`() =
|
fun `createAuthRequestWithUpdates with createNewAuthRequest Success and getAuthRequestUpdate with response date and no approval should emit Declined`() =
|
||||||
|
@ -305,6 +387,8 @@ class AuthRequestManagerTest {
|
||||||
pendingAuthRequest = PendingAuthRequestJson(
|
pendingAuthRequest = PendingAuthRequestJson(
|
||||||
requestId = authRequestResponseJson.id,
|
requestId = authRequestResponseJson.id,
|
||||||
requestPrivateKey = authRequestResponse.privateKey,
|
requestPrivateKey = authRequestResponse.privateKey,
|
||||||
|
requestAccessCode = authRequestResponse.accessCode,
|
||||||
|
requestFingerprint = authRequestResponse.fingerprint,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
assertEquals(CreateAuthRequestResult.Expired, awaitItem())
|
assertEquals(CreateAuthRequestResult.Expired, awaitItem())
|
||||||
|
|
|
@ -3566,6 +3566,8 @@ class AuthRepositoryTest {
|
||||||
val pendingAuthRequest = PendingAuthRequestJson(
|
val pendingAuthRequest = PendingAuthRequestJson(
|
||||||
requestId = "requestId",
|
requestId = "requestId",
|
||||||
requestPrivateKey = "requestPrivateKey",
|
requestPrivateKey = "requestPrivateKey",
|
||||||
|
requestFingerprint = "fingerprint",
|
||||||
|
requestAccessCode = "accessCode",
|
||||||
)
|
)
|
||||||
val successResponse = GET_TOKEN_RESPONSE_SUCCESS.copy(
|
val successResponse = GET_TOKEN_RESPONSE_SUCCESS.copy(
|
||||||
key = null,
|
key = null,
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.x8bit.bitwarden.ui.auth.feature.loginwithdevice
|
||||||
|
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.bitwarden.core.AuthRequestResponse
|
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequest
|
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequest
|
||||||
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestType
|
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestType
|
||||||
|
@ -166,7 +165,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.test {
|
viewModel.stateFlow.test {
|
||||||
assertEquals(DEFAULT_STATE, awaitItem())
|
assertEquals(DEFAULT_STATE, awaitItem())
|
||||||
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
||||||
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE),
|
CreateAuthRequestResult.Success(
|
||||||
|
authRequest = AUTH_REQUEST,
|
||||||
|
privateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
DEFAULT_STATE.copy(
|
DEFAULT_STATE.copy(
|
||||||
|
@ -196,9 +199,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
authRepository.login(
|
authRepository.login(
|
||||||
email = EMAIL,
|
email = EMAIL,
|
||||||
requestId = AUTH_REQUEST.id,
|
requestId = AUTH_REQUEST.id,
|
||||||
accessCode = AUTH_REQUEST_RESPONSE.accessCode,
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
||||||
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey,
|
requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
||||||
captchaToken = null,
|
captchaToken = null,
|
||||||
)
|
)
|
||||||
|
@ -227,7 +230,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.test {
|
viewModel.stateFlow.test {
|
||||||
assertEquals(initialState, awaitItem())
|
assertEquals(initialState, awaitItem())
|
||||||
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
||||||
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE),
|
CreateAuthRequestResult.Success(
|
||||||
|
authRequest = AUTH_REQUEST,
|
||||||
|
privateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
initialState.copy(
|
initialState.copy(
|
||||||
|
@ -279,7 +286,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.eventFlow.test {
|
viewModel.eventFlow.test {
|
||||||
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
||||||
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE),
|
CreateAuthRequestResult.Success(
|
||||||
|
authRequest = AUTH_REQUEST,
|
||||||
|
privateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
LoginWithDeviceEvent.NavigateToTwoFactorLogin(emailAddress = EMAIL),
|
LoginWithDeviceEvent.NavigateToTwoFactorLogin(emailAddress = EMAIL),
|
||||||
|
@ -291,9 +302,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
authRepository.login(
|
authRepository.login(
|
||||||
email = EMAIL,
|
email = EMAIL,
|
||||||
requestId = AUTH_REQUEST.id,
|
requestId = AUTH_REQUEST.id,
|
||||||
accessCode = AUTH_REQUEST_RESPONSE.accessCode,
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
||||||
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey,
|
requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
||||||
captchaToken = null,
|
captchaToken = null,
|
||||||
)
|
)
|
||||||
|
@ -319,7 +330,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.test {
|
viewModel.stateFlow.test {
|
||||||
assertEquals(DEFAULT_STATE, awaitItem())
|
assertEquals(DEFAULT_STATE, awaitItem())
|
||||||
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
||||||
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE),
|
CreateAuthRequestResult.Success(
|
||||||
|
authRequest = AUTH_REQUEST,
|
||||||
|
privateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
DEFAULT_STATE.copy(
|
DEFAULT_STATE.copy(
|
||||||
|
@ -353,9 +368,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
authRepository.login(
|
authRepository.login(
|
||||||
email = EMAIL,
|
email = EMAIL,
|
||||||
requestId = AUTH_REQUEST.id,
|
requestId = AUTH_REQUEST.id,
|
||||||
accessCode = AUTH_REQUEST_RESPONSE.accessCode,
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
||||||
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey,
|
requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
||||||
captchaToken = null,
|
captchaToken = null,
|
||||||
)
|
)
|
||||||
|
@ -382,7 +397,11 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.test {
|
viewModel.stateFlow.test {
|
||||||
assertEquals(DEFAULT_STATE, awaitItem())
|
assertEquals(DEFAULT_STATE, awaitItem())
|
||||||
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
mutableCreateAuthRequestWithUpdatesFlow.tryEmit(
|
||||||
CreateAuthRequestResult.Success(AUTH_REQUEST, AUTH_REQUEST_RESPONSE),
|
CreateAuthRequestResult.Success(
|
||||||
|
authRequest = AUTH_REQUEST,
|
||||||
|
privateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
DEFAULT_STATE.copy(
|
DEFAULT_STATE.copy(
|
||||||
|
@ -416,9 +435,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
authRepository.login(
|
authRepository.login(
|
||||||
email = EMAIL,
|
email = EMAIL,
|
||||||
requestId = AUTH_REQUEST.id,
|
requestId = AUTH_REQUEST.id,
|
||||||
accessCode = AUTH_REQUEST_RESPONSE.accessCode,
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
||||||
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey,
|
requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
||||||
captchaToken = null,
|
captchaToken = null,
|
||||||
)
|
)
|
||||||
|
@ -474,9 +493,9 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
|
||||||
authRepository.login(
|
authRepository.login(
|
||||||
email = EMAIL,
|
email = EMAIL,
|
||||||
requestId = AUTH_REQUEST.id,
|
requestId = AUTH_REQUEST.id,
|
||||||
accessCode = AUTH_REQUEST_RESPONSE.accessCode,
|
accessCode = AUTH_REQUEST_ACCESS_CODE,
|
||||||
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
asymmetricalKey = requireNotNull(AUTH_REQUEST.key),
|
||||||
requestPrivateKey = AUTH_REQUEST_RESPONSE.privateKey,
|
requestPrivateKey = AUTH_REQUEST_PRIVATE_KEY,
|
||||||
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
masterPasswordHash = AUTH_REQUEST.masterPasswordHash,
|
||||||
captchaToken = captchaToken,
|
captchaToken = captchaToken,
|
||||||
)
|
)
|
||||||
|
@ -603,12 +622,8 @@ private val AUTH_REQUEST = AuthRequest(
|
||||||
fingerprint = FINGERPRINT,
|
fingerprint = FINGERPRINT,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val AUTH_REQUEST_RESPONSE = AuthRequestResponse(
|
private const val AUTH_REQUEST_ACCESS_CODE = "accessCode"
|
||||||
privateKey = "private_key",
|
private const val AUTH_REQUEST_PRIVATE_KEY = "private_key"
|
||||||
publicKey = "public_key",
|
|
||||||
accessCode = "accessCode",
|
|
||||||
fingerprint = "fingerprint",
|
|
||||||
)
|
|
||||||
|
|
||||||
private val DEFAULT_LOGIN_DATA = LoginWithDeviceState.LoginData(
|
private val DEFAULT_LOGIN_DATA = LoginWithDeviceState.LoginData(
|
||||||
accessCode = "accessCode",
|
accessCode = "accessCode",
|
||||||
|
|
Loading…
Add table
Reference in a new issue