PM-10936: Add account apis for key connectors (#3748)
Some checks failed
Crowdin Push / Crowdin Push (push) Waiting to run
Scan / Check PR run (push) Failing after 0s
Scan / SAST scan (push) Has been skipped
Scan / Quality scan (push) Has been skipped
Test / Check PR run (push) Failing after 0s
Test / Test (push) Has been skipped

This commit is contained in:
David Perez 2024-08-15 13:53:48 -05:00 committed by GitHub
parent 244d259804
commit 4726cb743a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 102 additions and 0 deletions

View file

@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api
import com.x8bit.bitwarden.data.auth.datasource.network.model.CreateAccountKeysRequest
import com.x8bit.bitwarden.data.auth.datasource.network.model.DeleteAccountRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorKeyRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.ResetPasswordRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyOtpRequestJson
@ -13,6 +14,13 @@ import retrofit2.http.POST
* Defines raw calls under the /accounts API with authentication applied.
*/
interface AuthenticatedAccountsApi {
/**
* Converts the currently active account to a key-connector account.
*/
@POST("/accounts/convert-to-key-connector")
suspend fun convertToKeyConnector(): Result<Unit>
/**
* Creates the keys for the current account.
*/
@ -45,6 +53,12 @@ interface AuthenticatedAccountsApi {
@HTTP(method = "POST", path = "/accounts/password", hasBody = true)
suspend fun resetPassword(@Body body: ResetPasswordRequestJson): Result<Unit>
/**
* Sets the key connector key.
*/
@POST("/accounts/set-key-connector-key")
suspend fun setKeyConnectorKey(@Body body: KeyConnectorKeyRequestJson): Result<Unit>
/**
* Sets the password.
*/

View file

@ -0,0 +1,33 @@
package com.x8bit.bitwarden.data.auth.datasource.network.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Represents the request body used to create the key connector keys for an account.
*/
@Serializable
data class KeyConnectorKeyRequestJson(
@SerialName("key") val userKey: String,
@SerialName("keys") val keys: Keys,
@SerialName("kdf") val kdfType: KdfTypeJson,
@SerialName("kdfIterations") val kdfIterations: Int?,
@SerialName("kdfMemory") val kdfMemory: Int?,
@SerialName("kdfParallelism") val kdfParallelism: Int?,
@SerialName("orgIdentifier") val organizationIdentifier: String,
) {
/**
* A keys object containing public and private keys.
*
* @param publicKey the public key (encrypted).
* @param encryptedPrivateKey the private key (encrypted).
*/
@Serializable
data class Keys(
@SerialName("publicKey")
val publicKey: String,
@SerialName("encryptedPrivateKey")
val encryptedPrivateKey: String,
)
}

View file

@ -1,6 +1,7 @@
package com.x8bit.bitwarden.data.auth.datasource.network.service
import com.x8bit.bitwarden.data.auth.datasource.network.model.DeleteAccountResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorKeyRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.PasswordHintResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.ResetPasswordRequestJson
@ -11,6 +12,11 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequest
*/
interface AccountsService {
/**
* Converts the currently active account to a key-connector account.
*/
suspend fun convertToKeyConnector(): Result<Unit>
/**
* Creates a new account's keys.
*/
@ -49,6 +55,11 @@ interface AccountsService {
*/
suspend fun resetPassword(body: ResetPasswordRequestJson): Result<Unit>
/**
* Set the key connector key.
*/
suspend fun setKeyConnectorKey(body: KeyConnectorKeyRequestJson): Result<Unit>
/**
* Set the password.
*/

View file

@ -5,6 +5,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.api.AuthenticatedAccount
import com.x8bit.bitwarden.data.auth.datasource.network.model.CreateAccountKeysRequest
import com.x8bit.bitwarden.data.auth.datasource.network.model.DeleteAccountRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.DeleteAccountResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorKeyRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.PasswordHintRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.PasswordHintResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson
@ -21,6 +22,12 @@ class AccountsServiceImpl(
private val json: Json,
) : AccountsService {
/**
* Converts the currently active account to a key-connector account.
*/
override suspend fun convertToKeyConnector(): Result<Unit> =
authenticatedAccountsApi.convertToKeyConnector()
override suspend fun createAccountKeys(
publicKey: String,
encryptedPrivateKey: String,
@ -93,6 +100,10 @@ class AccountsServiceImpl(
}
}
override suspend fun setKeyConnectorKey(
body: KeyConnectorKeyRequestJson,
): Result<Unit> = authenticatedAccountsApi.setKeyConnectorKey(body)
override suspend fun setPassword(
body: SetPasswordRequestJson,
): Result<Unit> = authenticatedAccountsApi.setPassword(body)

View file

@ -2,6 +2,8 @@ package com.x8bit.bitwarden.data.auth.datasource.network.service
import com.x8bit.bitwarden.data.auth.datasource.network.api.AccountsApi
import com.x8bit.bitwarden.data.auth.datasource.network.api.AuthenticatedAccountsApi
import com.x8bit.bitwarden.data.auth.datasource.network.model.KdfTypeJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorKeyRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.PasswordHintResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson
@ -28,6 +30,16 @@ class AccountsServiceTest : BaseServiceTest() {
},
)
@Test
fun `convertToKeyConnector with empty response is success`() = runTest {
val response = MockResponse().setBody("")
server.enqueue(response)
val result = service.convertToKeyConnector()
assertTrue(result.isSuccess)
}
@Test
fun `createAccountKeys with empty response is success`() = runTest {
val publicKey = "publicKey"
@ -173,4 +185,25 @@ class AccountsServiceTest : BaseServiceTest() {
)
assertTrue(result.isSuccess)
}
@Test
fun `setKeyConnectorKey with empty response is success`() = runTest {
val response = MockResponse().setBody("")
server.enqueue(response)
val result = service.setKeyConnectorKey(
body = KeyConnectorKeyRequestJson(
organizationIdentifier = "organizationId",
kdfIterations = 7,
kdfMemory = 1,
kdfParallelism = 2,
kdfType = KdfTypeJson.ARGON2_ID,
userKey = "encryptedUserKey",
keys = KeyConnectorKeyRequestJson.Keys(
publicKey = "public",
encryptedPrivateKey = "private",
),
),
)
assertTrue(result.isSuccess)
}
}