mirror of
https://github.com/bitwarden/android.git
synced 2024-11-29 06:18:52 +03:00
Update AuthRequestManager for TDE (#1223)
This commit is contained in:
parent
f09d9473f7
commit
5d40d68b3f
3 changed files with 108 additions and 0 deletions
|
@ -36,6 +36,11 @@ interface AuthRequestManager {
|
||||||
*/
|
*/
|
||||||
fun getAuthRequestsWithUpdates(): Flow<AuthRequestsUpdatesResult>
|
fun getAuthRequestsWithUpdates(): Flow<AuthRequestsUpdatesResult>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an [AuthRequest] by its request ID.
|
||||||
|
*/
|
||||||
|
suspend fun getAuthRequestIfApproved(requestId: String): Result<AuthRequest>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of the current user's [AuthRequest]s.
|
* Get a list of the current user's [AuthRequest]s.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.manager
|
||||||
|
|
||||||
import com.bitwarden.core.AuthRequestResponse
|
import com.bitwarden.core.AuthRequestResponse
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.PendingAuthRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestTypeJson
|
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestTypeJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.AuthRequestsService
|
import com.x8bit.bitwarden.data.auth.datasource.network.service.AuthRequestsService
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.service.NewAuthRequestService
|
import com.x8bit.bitwarden.data.auth.datasource.network.service.NewAuthRequestService
|
||||||
|
@ -246,6 +247,31 @@ class AuthRequestManagerImpl(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getAuthRequestIfApproved(requestId: String): Result<AuthRequest> =
|
||||||
|
authRequestsService
|
||||||
|
.getAuthRequest(requestId)
|
||||||
|
.flatMap { request ->
|
||||||
|
if (request.requestApproved == true) {
|
||||||
|
getFingerprintPhrase(request.publicKey).map { fingerprint ->
|
||||||
|
AuthRequest(
|
||||||
|
id = request.id,
|
||||||
|
publicKey = request.publicKey,
|
||||||
|
platform = request.platform,
|
||||||
|
ipAddress = request.ipAddress,
|
||||||
|
key = request.key,
|
||||||
|
masterPasswordHash = request.masterPasswordHash,
|
||||||
|
creationDate = request.creationDate,
|
||||||
|
responseDate = request.responseDate,
|
||||||
|
requestApproved = true,
|
||||||
|
originUrl = request.originUrl,
|
||||||
|
fingerprint = fingerprint,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IllegalStateException("Request not approved.").asFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getAuthRequests(): AuthRequestsResult =
|
override suspend fun getAuthRequests(): AuthRequestsResult =
|
||||||
authRequestsService
|
authRequestsService
|
||||||
.getAuthRequests()
|
.getAuthRequests()
|
||||||
|
@ -335,6 +361,17 @@ class AuthRequestManagerImpl(
|
||||||
fingerprint = authRequestResponse.fingerprint,
|
fingerprint = authRequestResponse.fingerprint,
|
||||||
authRequestType = authRequestType,
|
authRequestType = authRequestType,
|
||||||
)
|
)
|
||||||
|
.onSuccess {
|
||||||
|
if (authRequestType == AuthRequestTypeJson.ADMIN_APPROVAL) {
|
||||||
|
authDiskSource.storePendingAuthRequest(
|
||||||
|
userId = requireNotNull(activeUserId),
|
||||||
|
pendingAuthRequest = PendingAuthRequestJson(
|
||||||
|
requestId = it.id,
|
||||||
|
requestPrivateKey = authRequestResponse.privateKey,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
.map { request ->
|
.map { request ->
|
||||||
AuthRequest(
|
AuthRequest(
|
||||||
id = request.id,
|
id = request.id,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import app.cash.turbine.test
|
||||||
import com.bitwarden.core.AuthRequestResponse
|
import com.bitwarden.core.AuthRequestResponse
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||||
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.PendingAuthRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestTypeJson
|
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestTypeJson
|
||||||
|
@ -29,6 +30,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.advanceTimeBy
|
import kotlinx.coroutines.test.advanceTimeBy
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.time.Clock
|
import java.time.Clock
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
@ -240,6 +242,7 @@ class AuthRequestManagerTest {
|
||||||
fun `createAuthRequestWithUpdates with createNewAuthRequest Success and getAuthRequestUpdate with old creation date should emit Expired`() =
|
fun `createAuthRequestWithUpdates with createNewAuthRequest Success and getAuthRequestUpdate with old creation date should emit Expired`() =
|
||||||
runTest {
|
runTest {
|
||||||
val email = "email@email.com"
|
val email = "email@email.com"
|
||||||
|
fakeAuthDiskSource.userState = SINGLE_USER_STATE
|
||||||
val authRequestResponse = AUTH_REQUEST_RESPONSE
|
val authRequestResponse = AUTH_REQUEST_RESPONSE
|
||||||
val authRequestResponseJson = AuthRequestsResponseJson.AuthRequest(
|
val authRequestResponseJson = AuthRequestsResponseJson.AuthRequest(
|
||||||
id = "1",
|
id = "1",
|
||||||
|
@ -300,6 +303,13 @@ class AuthRequestManagerTest {
|
||||||
assertEquals(CreateAuthRequestResult.Expired, awaitItem())
|
assertEquals(CreateAuthRequestResult.Expired, awaitItem())
|
||||||
awaitComplete()
|
awaitComplete()
|
||||||
}
|
}
|
||||||
|
fakeAuthDiskSource.assertPendingAuthRequest(
|
||||||
|
userId = USER_ID,
|
||||||
|
pendingAuthRequest = PendingAuthRequestJson(
|
||||||
|
requestId = authRequestResponseJson.id,
|
||||||
|
requestPrivateKey = authRequestResponse.privateKey,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
@Suppress("MaxLineLength")
|
||||||
|
@ -777,6 +787,62 @@ class AuthRequestManagerTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getAuthRequestIfApproved should return failure when service returns failure`() = runTest {
|
||||||
|
val requestId = "requestId"
|
||||||
|
coEvery {
|
||||||
|
authRequestsService.getAuthRequest(requestId)
|
||||||
|
} returns Throwable("Fail").asFailure()
|
||||||
|
|
||||||
|
val result = repository.getAuthRequestIfApproved(requestId)
|
||||||
|
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
authRequestsService.getAuthRequest(requestId)
|
||||||
|
}
|
||||||
|
assertTrue(result.isFailure)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getAuthRequestIfApproved should return failure when request is not approved`() = runTest {
|
||||||
|
val requestId = "requestId"
|
||||||
|
val response = AUTH_REQUESTS_RESPONSE_JSON_AUTH_RESPONSE.copy(requestApproved = false)
|
||||||
|
coEvery { authRequestsService.getAuthRequest(requestId) } returns response.asSuccess()
|
||||||
|
|
||||||
|
val result = repository.getAuthRequestIfApproved(requestId)
|
||||||
|
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
authRequestsService.getAuthRequest(requestId)
|
||||||
|
}
|
||||||
|
assertTrue(result.isFailure)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getAuthRequestIfApproved should return success when request is approved`() = runTest {
|
||||||
|
val requestId = "requestId"
|
||||||
|
fakeAuthDiskSource.userState = SINGLE_USER_STATE
|
||||||
|
coEvery {
|
||||||
|
authRequestsService.getAuthRequest(requestId)
|
||||||
|
} returns AUTH_REQUESTS_RESPONSE_JSON_AUTH_RESPONSE.asSuccess()
|
||||||
|
fakeAuthDiskSource.userState = SINGLE_USER_STATE
|
||||||
|
coEvery {
|
||||||
|
authSdkSource.getUserFingerprint(
|
||||||
|
email = EMAIL,
|
||||||
|
publicKey = AUTH_REQUESTS_RESPONSE_JSON_AUTH_RESPONSE.publicKey,
|
||||||
|
)
|
||||||
|
} returns FINGER_PRINT.asSuccess()
|
||||||
|
|
||||||
|
val result = repository.getAuthRequestIfApproved(requestId)
|
||||||
|
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
authRequestsService.getAuthRequest(requestId)
|
||||||
|
authSdkSource.getUserFingerprint(
|
||||||
|
email = EMAIL,
|
||||||
|
publicKey = AUTH_REQUESTS_RESPONSE_JSON_AUTH_RESPONSE.publicKey,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertEquals(AUTH_REQUEST.asSuccess(), result)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getAuthRequests should return failure when service returns failure`() = runTest {
|
fun `getAuthRequests should return failure when service returns failure`() = runTest {
|
||||||
coEvery { authRequestsService.getAuthRequests() } returns Throwable("Fail").asFailure()
|
coEvery { authRequestsService.getAuthRequests() } returns Throwable("Fail").asFailure()
|
||||||
|
|
Loading…
Reference in a new issue