[PM-23278] Add updateKdf service call and test

This commit is contained in:
André Bispo
2025-09-09 10:14:24 +01:00
parent 5ff44d6133
commit a0bbc1a313
8 changed files with 154 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ import com.bitwarden.network.model.DeleteAccountRequestJson
import com.bitwarden.network.model.NetworkResult
import com.bitwarden.network.model.ResetPasswordRequestJson
import com.bitwarden.network.model.SetPasswordRequestJson
import com.bitwarden.network.model.UpdateKdfJsonRequest
import com.bitwarden.network.model.VerifyOtpRequestJson
import retrofit2.http.Body
import retrofit2.http.HTTP
@@ -36,6 +37,12 @@ internal interface AuthenticatedAccountsApi {
@POST("/accounts/request-otp")
suspend fun requestOtp(): NetworkResult<Unit>
/**
* Update the KDF settings for the current account.
*/
@POST("/accounts/kdf")
suspend fun updateKdf(@Body body: UpdateKdfJsonRequest): NetworkResult<Unit>
@POST("/accounts/verify-otp")
suspend fun verifyOtp(
@Body body: VerifyOtpRequestJson,

View File

@@ -0,0 +1,22 @@
package com.bitwarden.network.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Represents the request body used to create the kdf settings.
*/
@Serializable
data class KdfJsonRequest(
@SerialName("KdfType")
val kdfType: KdfTypeJson,
@SerialName("Iterations")
val iterations: Int,
@SerialName("Memory")
val memory: Int?,
@SerialName("Parallelism")
val parallelism: Int?,
)

View File

@@ -0,0 +1,19 @@
package com.bitwarden.network.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Represents the request body used to authenticate with the master password.
*/
@Serializable
data class MasterPasswordAuthenticationDataJsonRequest(
@SerialName("Kdf")
val kdf: KdfJsonRequest,
@SerialName("MasterPasswordAuthenticationHash")
val masterPasswordAuthenticationHash: String,
@SerialName("Salt")
val salt: String,
)

View File

@@ -0,0 +1,19 @@
package com.bitwarden.network.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Represents the request body used to unlock with the master password.
*/
@Serializable
data class MasterPasswordUnlockDataJsonRequest(
@SerialName("Kdf")
val kdf: KdfJsonRequest,
@SerialName("MasterKeyWrappedUserKey")
val masterKeyWrappedUserKey: String,
@SerialName("Salt")
val salt: String,
)

View File

@@ -0,0 +1,25 @@
package com.bitwarden.network.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Represents the request body used to update the user's kdf settings.
*/
@Serializable
data class UpdateKdfJsonRequest(
@SerialName("authenticationData")
val authenticationData: MasterPasswordAuthenticationDataJsonRequest,
@SerialName("key")
val key: String,
@SerialName("masterPasswordHash")
val masterPasswordHash: String,
@SerialName("newMasterPasswordHash")
val newMasterPasswordHash: String,
@SerialName("unlockData")
val unlockData: MasterPasswordUnlockDataJsonRequest,
)

View File

@@ -8,6 +8,7 @@ import com.bitwarden.network.model.ResendEmailRequestJson
import com.bitwarden.network.model.ResendNewDeviceOtpRequestJson
import com.bitwarden.network.model.ResetPasswordRequestJson
import com.bitwarden.network.model.SetPasswordRequestJson
import com.bitwarden.network.model.UpdateKdfJsonRequest
/**
* Provides an API for querying accounts endpoints.
@@ -109,4 +110,9 @@ interface AccountsService {
accessToken: String,
masterKey: String,
): Result<Unit>
/**
* Update the KDF settings for the current account.
*/
suspend fun updateKdf(body: UpdateKdfJsonRequest): Result<Unit>
}

View File

@@ -16,6 +16,7 @@ import com.bitwarden.network.model.ResendEmailRequestJson
import com.bitwarden.network.model.ResendNewDeviceOtpRequestJson
import com.bitwarden.network.model.ResetPasswordRequestJson
import com.bitwarden.network.model.SetPasswordRequestJson
import com.bitwarden.network.model.UpdateKdfJsonRequest
import com.bitwarden.network.model.VerifyOtpRequestJson
import com.bitwarden.network.model.toBitwardenError
import com.bitwarden.network.util.HEADER_VALUE_BEARER_PREFIX
@@ -183,4 +184,9 @@ internal class AccountsServiceImpl(
body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey),
)
.toResult()
override suspend fun updateKdf(body: UpdateKdfJsonRequest): Result<Unit> =
authenticatedAccountsApi
.updateKdf(body)
.toResult()
}

View File

@@ -6,15 +6,19 @@ import com.bitwarden.network.api.AuthenticatedKeyConnectorApi
import com.bitwarden.network.api.UnauthenticatedAccountsApi
import com.bitwarden.network.api.UnauthenticatedKeyConnectorApi
import com.bitwarden.network.base.BaseServiceTest
import com.bitwarden.network.model.KdfJsonRequest
import com.bitwarden.network.model.KdfTypeJson
import com.bitwarden.network.model.KeyConnectorKeyRequestJson
import com.bitwarden.network.model.KeyConnectorMasterKeyResponseJson
import com.bitwarden.network.model.MasterPasswordAuthenticationDataJsonRequest
import com.bitwarden.network.model.MasterPasswordUnlockDataJsonRequest
import com.bitwarden.network.model.PasswordHintResponseJson
import com.bitwarden.network.model.RegisterRequestJson
import com.bitwarden.network.model.ResendEmailRequestJson
import com.bitwarden.network.model.ResendNewDeviceOtpRequestJson
import com.bitwarden.network.model.ResetPasswordRequestJson
import com.bitwarden.network.model.SetPasswordRequestJson
import com.bitwarden.network.model.UpdateKdfJsonRequest
import kotlinx.coroutines.test.runTest
import okhttp3.mockwebserver.MockResponse
import org.junit.jupiter.api.Assertions.assertEquals
@@ -264,4 +268,50 @@ class AccountsServiceTest : BaseServiceTest() {
)
assertTrue(result.isSuccess)
}
@Test
fun `updateKdf success should return Success`() = runTest {
val response = MockResponse().setResponseCode(200)
server.enqueue(response)
val result = service.updateKdf(body = UPDATE_KDF_REQUEST)
assertTrue(result.isSuccess)
}
@Test
fun `updateKdf failure should return Failure`() = runTest {
val response = MockResponse().setResponseCode(400)
server.enqueue(response)
val result = service.updateKdf(body = UPDATE_KDF_REQUEST)
assertTrue(result.isFailure)
}
private val UPDATE_KDF_REQUEST = UpdateKdfJsonRequest(
authenticationData = MasterPasswordAuthenticationDataJsonRequest(
kdf = KdfJsonRequest(
kdfType = KdfTypeJson.PBKDF2_SHA256,
iterations = 7,
memory = 1,
parallelism = 2,
),
masterPasswordAuthenticationHash = "mockMasterPasswordHash",
salt = "mockSalt",
),
key = "mockKey",
masterPasswordHash = "mockMasterPasswordHash",
newMasterPasswordHash = "mockNewMasterPasswordHash",
unlockData = MasterPasswordUnlockDataJsonRequest(
kdf = KdfJsonRequest(
kdfType = KdfTypeJson.PBKDF2_SHA256,
iterations = 7,
memory = 1,
parallelism = 2,
),
masterKeyWrappedUserKey = "mockMasterPasswordKey",
salt = "mockSalt",
),
)
}