diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt index ded764d96a..c323e8643e 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt @@ -2,8 +2,10 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import com.x8bit.bitwarden.data.auth.datasource.network.model.DeleteAccountRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResetPasswordRequestJson +import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequestJson import retrofit2.http.Body import retrofit2.http.HTTP +import retrofit2.http.POST /** * Defines raw calls under the /accounts API with authentication applied. @@ -26,4 +28,10 @@ interface AuthenticatedAccountsApi { */ @HTTP(method = "POST", path = "/accounts/password", hasBody = true) suspend fun resetPassword(@Body body: ResetPasswordRequestJson): Result + + /** + * Sets the password. + */ + @POST("/accounts/set-password") + suspend fun setPassword(@Body body: SetPasswordRequestJson): Result } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/SetPasswordRequestJson.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/SetPasswordRequestJson.kt new file mode 100644 index 0000000000..0586ac633e --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/model/SetPasswordRequestJson.kt @@ -0,0 +1,48 @@ +package com.x8bit.bitwarden.data.auth.datasource.network.model + +import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJson.Keys +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Request body for resetting the password. + * + * @property kdfType The KDF type. + * @property kdfIterations The number of iterations when calculating a user's password. + * @property kdfMemory The amount of memory to use when calculating a password hash (MB). + * @property kdfParallelism The number of threads to use when calculating a password hash. + * @param key The user key for the request (encrypted). + * @param keys A [Keys] object containing public and private keys. + * @param organizationIdentifier The SSO organization identifier. + * @param passwordHash The hash of the user's new password. + * @param passwordHint The hint for the master password (nullable). + */ +@Serializable +data class SetPasswordRequestJson( + @SerialName("kdf") + val kdfType: KdfTypeJson? = null, + + @SerialName("kdfIterations") + val kdfIterations: Int? = null, + + @SerialName("kdfMemory") + val kdfMemory: Int? = null, + + @SerialName("kdfParallelism") + val kdfParallelism: Int? = null, + + @SerialName("key") + val key: String, + + @SerialName("keys") + val keys: Keys, + + @SerialName("orgIdentifier") + val organizationIdentifier: String, + + @SerialName("masterPasswordHash") + val passwordHash: String?, + + @SerialName("masterPasswordHint") + val passwordHint: String?, +) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsService.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsService.kt index 43b6847c81..3b90508609 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsService.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsService.kt @@ -6,6 +6,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJso import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResetPasswordRequestJson +import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequestJson /** * Provides an API for querying accounts endpoints. @@ -41,4 +42,9 @@ interface AccountsService { * Reset the password. */ suspend fun resetPassword(body: ResetPasswordRequestJson): Result + + /** + * Set the password. + */ + suspend fun setPassword(body: SetPasswordRequestJson): Result } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt index 155f83d688..7d29be97ef 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt @@ -11,6 +11,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJso import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson 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.platform.datasource.network.model.toBitwardenError import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull import kotlinx.serialization.json.Json @@ -71,4 +72,8 @@ class AccountsServiceImpl( authenticatedAccountsApi.resetPassword(body = body) } } + + override suspend fun setPassword( + body: SetPasswordRequestJson, + ): Result = authenticatedAccountsApi.setPassword(body) } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceTest.kt index a86c3b1726..60864ddda7 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceTest.kt @@ -9,6 +9,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJso import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson 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.platform.base.BaseServiceTest import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json @@ -258,6 +259,29 @@ class AccountsServiceTest : BaseServiceTest() { assertTrue(result.isSuccess) } + @Test + fun `setPassword with empty response is success`() = runTest { + val response = MockResponse().setBody("") + server.enqueue(response) + val result = service.setPassword( + body = SetPasswordRequestJson( + passwordHash = "passwordHash", + passwordHint = "passwordHint", + organizationIdentifier = "organizationId", + kdfIterations = 7, + kdfMemory = 1, + kdfParallelism = 2, + kdfType = null, + key = "encryptedUserKey", + keys = RegisterRequestJson.Keys( + publicKey = "public", + encryptedPrivateKey = "private", + ), + ), + ) + assertTrue(result.isSuccess) + } + companion object { private const val EMAIL = "email" private val registerRequestBody = RegisterRequestJson(