From 75ce374c3c93f9e3732eb5b287400902a28e3d14 Mon Sep 17 00:00:00 2001 From: Seth Onyango <57979366+sethonyango@users.noreply.github.com> Date: Fri, 28 Jun 2024 08:23:05 +0300 Subject: [PATCH] Migrate from json patch to json merge patch (#280) * Update libs.versions.toml * Update Falu's API version * Migrate from json patch to Json merge patch --------- Co-authored-by: Seth Onyango <57979366+SecyWecy@users.noreply.github.com> --- .../src/main/java/io/falu/core/ApiVersion.kt | 2 +- .../identity/IdentityVerificationViewModel.kt | 6 +++--- .../api/IdentityVerificationApiClient.kt | 6 +++--- .../verification/VerificationUpdateOptions.kt | 12 ++++++++++++ .../identity/capture/AbstractCaptureFragment.kt | 7 +++---- .../documents/DocumentSelectionFragment.kt | 7 +++---- .../io/falu/identity/selfie/SelfieFragment.kt | 17 ++++++++--------- .../falu/identity/utils/FragmentExtensions.kt | 6 +++--- .../IdentificationVerificationFragment.kt | 7 +++---- .../io/falu/identity/welcome/WelcomeFragment.kt | 7 ++++--- .../api/IdentityVerificationApiClientTests.kt | 6 +++--- 11 files changed, 46 insertions(+), 37 deletions(-) create mode 100644 identity/src/main/java/io/falu/identity/api/models/verification/VerificationUpdateOptions.kt diff --git a/falu-core/src/main/java/io/falu/core/ApiVersion.kt b/falu-core/src/main/java/io/falu/core/ApiVersion.kt index 5687f6d0..b112817a 100644 --- a/falu-core/src/main/java/io/falu/core/ApiVersion.kt +++ b/falu-core/src/main/java/io/falu/core/ApiVersion.kt @@ -19,7 +19,7 @@ data class ApiVersion internal constructor(internal val version: String) { @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) companion object { - private const val API_VERSION_CODE: String = "2022-09-01" + private const val API_VERSION_CODE: String = "2024-06-01" private val INSTANCE = ApiVersion(API_VERSION_CODE) diff --git a/identity/src/main/java/io/falu/identity/IdentityVerificationViewModel.kt b/identity/src/main/java/io/falu/identity/IdentityVerificationViewModel.kt index 30811ea5..2f6d7757 100644 --- a/identity/src/main/java/io/falu/identity/IdentityVerificationViewModel.kt +++ b/identity/src/main/java/io/falu/identity/IdentityVerificationViewModel.kt @@ -26,6 +26,7 @@ import io.falu.identity.api.models.DocumentSide import io.falu.identity.api.models.UploadMethod import io.falu.identity.api.models.country.SupportedCountry import io.falu.identity.api.models.verification.Verification +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationUploadRequest import io.falu.identity.api.models.verification.VerificationUploadResult import io.falu.identity.utils.FileUtils @@ -40,7 +41,6 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import software.tingle.api.HttpApiResponseProblem import software.tingle.api.ResourceResponse -import software.tingle.api.patch.JsonPatchDocument import java.io.File import java.io.InputStream import kotlin.coroutines.CoroutineContext @@ -256,14 +256,14 @@ internal class IdentityVerificationViewModel( } internal fun updateVerification( - document: JsonPatchDocument, + updateOptions: VerificationUpdateOptions, onSuccess: ((Verification) -> Unit), onError: ((Throwable?) -> Unit), onFailure: ((Throwable) -> Unit) ) { launch(Dispatchers.IO) { runCatching { - apiClient.updateVerification(contractArgs.verificationId, document) + apiClient.updateVerification(contractArgs.verificationId, updateOptions) }.fold( onSuccess = { response -> handleResponse( diff --git a/identity/src/main/java/io/falu/identity/api/IdentityVerificationApiClient.kt b/identity/src/main/java/io/falu/identity/api/IdentityVerificationApiClient.kt index 052d5cd0..db106c6d 100644 --- a/identity/src/main/java/io/falu/identity/api/IdentityVerificationApiClient.kt +++ b/identity/src/main/java/io/falu/identity/api/IdentityVerificationApiClient.kt @@ -11,6 +11,7 @@ import io.falu.core.exceptions.AuthenticationException import io.falu.core.models.FaluFile import io.falu.core.utils.getMediaType import io.falu.identity.api.models.verification.Verification +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationUploadRequest import okhttp3.MultipartBody import okhttp3.OkHttpClient @@ -21,7 +22,6 @@ import okhttp3.logging.HttpLoggingInterceptor import software.tingle.api.AbstractHttpApiClient import software.tingle.api.ResourceResponse import software.tingle.api.authentication.AuthenticationHeaderProvider -import software.tingle.api.patch.JsonPatchDocument import java.io.File import java.util.concurrent.TimeUnit @@ -53,11 +53,11 @@ internal class IdentityVerificationApiClient( ) fun updateVerification( verification: String, - document: JsonPatchDocument + updateOptions: VerificationUpdateOptions ): ResourceResponse { val builder = Request.Builder() .url("$BASE_URL/v1/identity/verifications/$verification/workflow") - .patch(makeJson(document.getOperations()).toRequestBody(MEDIA_TYPE_PATH_JSON)) + .patch(makeJson(updateOptions).toRequestBody(MEDIA_TYPE_PATCH_MERGE)) return execute(builder, Verification::class.java) } diff --git a/identity/src/main/java/io/falu/identity/api/models/verification/VerificationUpdateOptions.kt b/identity/src/main/java/io/falu/identity/api/models/verification/VerificationUpdateOptions.kt new file mode 100644 index 00000000..80fbab1f --- /dev/null +++ b/identity/src/main/java/io/falu/identity/api/models/verification/VerificationUpdateOptions.kt @@ -0,0 +1,12 @@ +package io.falu.identity.api.models.verification + +import com.google.gson.annotations.SerializedName + +internal data class VerificationUpdateOptions( + val consent: Boolean? = null, + val document: VerificationDocumentUpload? = null, + val country: String? = null, + val selfie: VerificationSelfieUpload? = null, + @SerializedName("id_number") + val idNumber: VerificationIdNumberUpload? = null +) \ No newline at end of file diff --git a/identity/src/main/java/io/falu/identity/capture/AbstractCaptureFragment.kt b/identity/src/main/java/io/falu/identity/capture/AbstractCaptureFragment.kt index 7a7e416d..738358b0 100644 --- a/identity/src/main/java/io/falu/identity/capture/AbstractCaptureFragment.kt +++ b/identity/src/main/java/io/falu/identity/capture/AbstractCaptureFragment.kt @@ -21,6 +21,7 @@ import io.falu.identity.api.DocumentUploadDisposition import io.falu.identity.api.models.DocumentSide import io.falu.identity.api.models.IdentityDocumentType import io.falu.identity.api.models.UploadMethod +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationUploadRequest import io.falu.identity.camera.CameraPermissionsFragment import io.falu.identity.capture.scan.DocumentScanViewModel @@ -35,7 +36,6 @@ import io.falu.identity.utils.serializable import io.falu.identity.utils.submitVerificationData import io.falu.identity.utils.toBitmap import io.falu.identity.utils.updateVerification -import software.tingle.api.patch.JsonPatchDocument internal abstract class AbstractCaptureFragment( identityViewModelFactory: ViewModelProvider.Factory @@ -189,10 +189,9 @@ internal abstract class AbstractCaptureFragment( @IdRes source: Int, verificationRequest: VerificationUploadRequest ) { - val patchDocument = JsonPatchDocument() - .replace("/document", verificationRequest.document) + val patchRequest = VerificationUpdateOptions(document = verificationRequest.document) - updateVerification(identityViewModel, patchDocument, source, onSuccess = { + updateVerification(identityViewModel, patchRequest, source, onSuccess = { attemptDocumentSubmission(source, verificationRequest) }) } diff --git a/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt b/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt index 1fbd7621..4b2b9b21 100644 --- a/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt +++ b/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt @@ -14,12 +14,12 @@ import io.falu.identity.R import io.falu.identity.api.models.IdentityDocumentType import io.falu.identity.api.models.country.SupportedCountry import io.falu.identity.api.models.verification.Verification +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationType import io.falu.identity.countries.CountriesAdapter import io.falu.identity.databinding.FragmentDocumentSelectionBinding import io.falu.identity.utils.navigateToApiResponseProblemFragment import io.falu.identity.utils.updateVerification -import software.tingle.api.patch.JsonPatchDocument class DocumentSelectionFragment(private val factory: ViewModelProvider.Factory) : Fragment() { @@ -124,8 +124,7 @@ class DocumentSelectionFragment(private val factory: ViewModelProvider.Factory) private fun updateVerification(verification: Verification) { binding.buttonContinue.showProgress() val country = binding.buttonContinue.tag as SupportedCountry - val document = JsonPatchDocument() - .replace("country", country.country.code) + val updateOptions = VerificationUpdateOptions(country = country.country.code) val action = if (verification.type != VerificationType.IDENTITY_NUMBER) { R.id.action_fragment_document_selection_to_fragment_document_capture_methods @@ -135,7 +134,7 @@ class DocumentSelectionFragment(private val factory: ViewModelProvider.Factory) updateVerification( viewModel, - document, + updateOptions, source = R.id.action_fragment_welcome_to_fragment_document_selection, onSuccess = { val bundle = bundleOf(KEY_IDENTITY_DOCUMENT_TYPE to identityDocumentType) diff --git a/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt b/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt index 3002e3bb..b58038f6 100644 --- a/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt +++ b/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt @@ -19,6 +19,7 @@ import io.falu.identity.ai.FaceDetectionOutput import io.falu.identity.analytics.AnalyticsDisposition import io.falu.identity.api.models.UploadMethod import io.falu.identity.api.models.verification.Verification +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationSelfieUpload import io.falu.identity.api.models.verification.VerificationUploadRequest import io.falu.identity.camera.CameraView @@ -30,7 +31,6 @@ import io.falu.identity.utils.navigateToApiResponseProblemFragment import io.falu.identity.utils.navigateToErrorFragment import io.falu.identity.utils.submitVerificationData import io.falu.identity.utils.updateVerification -import software.tingle.api.patch.JsonPatchDocument internal class SelfieFragment(identityViewModelFactory: ViewModelProvider.Factory) : Fragment() { @@ -175,16 +175,15 @@ internal class SelfieFragment(identityViewModelFactory: ViewModelProvider.Factor } private fun submitSelfieAndUploadedDocuments(file: FaluFile) { - val selfie = - VerificationSelfieUpload( - UploadMethod.MANUAL, - file = file.id, - variance = 0F - ) + val selfie = VerificationSelfieUpload( + UploadMethod.MANUAL, + file = file.id, + variance = 0F + ) - val document = JsonPatchDocument().replace("/selfie", selfie) + val updateOptions = VerificationUpdateOptions(selfie = selfie) - updateVerification(identityViewModel, document, R.id.fragment_selfie, onSuccess = { + updateVerification(identityViewModel, updateOptions, R.id.fragment_selfie, onSuccess = { selfie.camera = binding.viewCamera.cameraSettings verificationRequest.selfie = selfie submitVerificationData(identityViewModel, R.id.fragment_selfie, verificationRequest) diff --git a/identity/src/main/java/io/falu/identity/utils/FragmentExtensions.kt b/identity/src/main/java/io/falu/identity/utils/FragmentExtensions.kt index 96facd69..ca31494b 100644 --- a/identity/src/main/java/io/falu/identity/utils/FragmentExtensions.kt +++ b/identity/src/main/java/io/falu/identity/utils/FragmentExtensions.kt @@ -11,22 +11,22 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import io.falu.core.exceptions.ApiException import io.falu.identity.IdentityVerificationViewModel import io.falu.identity.R +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationUploadRequest import io.falu.identity.capture.scan.DocumentScanViewModel import io.falu.identity.error.ErrorFragment.Companion.navigateWithApiExceptions import io.falu.identity.error.ErrorFragment.Companion.navigateWithFailure import io.falu.identity.error.ErrorFragment.Companion.navigateWithRequirementErrors import software.tingle.api.HttpApiResponseProblem -import software.tingle.api.patch.JsonPatchDocument import java.io.File internal fun Fragment.updateVerification( viewModel: IdentityVerificationViewModel, - document: JsonPatchDocument, + updateOptions: VerificationUpdateOptions, @IdRes source: Int, onSuccess: (() -> Unit) ) { - viewModel.updateVerification(document, + viewModel.updateVerification(updateOptions, onSuccess = { when { else -> { diff --git a/identity/src/main/java/io/falu/identity/verification/IdentificationVerificationFragment.kt b/identity/src/main/java/io/falu/identity/verification/IdentificationVerificationFragment.kt index a59dadca..1b28b756 100644 --- a/identity/src/main/java/io/falu/identity/verification/IdentificationVerificationFragment.kt +++ b/identity/src/main/java/io/falu/identity/verification/IdentificationVerificationFragment.kt @@ -14,6 +14,7 @@ import io.falu.identity.R import io.falu.identity.api.models.IdentityDocumentType import io.falu.identity.api.models.verification.Gender import io.falu.identity.api.models.verification.VerificationIdNumberUpload +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationUploadRequest import io.falu.identity.databinding.FragmentIdentificationVerificationBinding import io.falu.identity.documents.DocumentSelectionFragment @@ -22,7 +23,6 @@ import io.falu.identity.utils.showDatePickerDialog import io.falu.identity.utils.showDialog import io.falu.identity.utils.submitVerificationData import io.falu.identity.utils.updateVerification -import software.tingle.api.patch.JsonPatchDocument import java.util.Date internal class IdentificationVerificationFragment(factory: ViewModelProvider.Factory) : Fragment() { @@ -77,12 +77,11 @@ internal class IdentificationVerificationFragment(factory: ViewModelProvider.Fac } private fun updateVerification(request: VerificationUploadRequest, source: Int) { - val patchDocument = JsonPatchDocument() - .replace("/id_number", request.idNumber) + val updateOptions = VerificationUpdateOptions(idNumber = request.idNumber) updateVerification( viewModel, - patchDocument, + updateOptions, source, onSuccess = { submitVerificationData(viewModel, source, request) }) } diff --git a/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt b/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt index 549454d4..c4be42fc 100644 --- a/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt +++ b/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt @@ -16,12 +16,12 @@ import io.falu.identity.IdentityVerificationViewModel import io.falu.identity.R import io.falu.identity.analytics.AnalyticsDisposition import io.falu.identity.api.models.verification.Verification +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.databinding.FragmentWelcomeBinding import io.falu.identity.error.ErrorFragment.Companion.navigateWithDepletedAttempts import io.falu.identity.utils.navigateToApiResponseProblemFragment import io.falu.identity.utils.updateVerification import software.tingle.api.HttpApiResponseProblem -import software.tingle.api.patch.JsonPatchDocument internal class WelcomeFragment( private val factory: ViewModelProvider.Factory, @@ -88,11 +88,12 @@ internal class WelcomeFragment( } private fun submitConsentData() { - val document = JsonPatchDocument().replace("consent", true) + val updateOptions = VerificationUpdateOptions(consent = true) + binding.buttonAccept.showProgress() updateVerification( viewModel, - document, + updateOptions, source = R.id.fragment_welcome, onSuccess = { binding.buttonAccept.showProgress() diff --git a/identity/src/test/java/io/falu/identity/api/IdentityVerificationApiClientTests.kt b/identity/src/test/java/io/falu/identity/api/IdentityVerificationApiClientTests.kt index cdcdf19f..bb5a2a52 100644 --- a/identity/src/test/java/io/falu/identity/api/IdentityVerificationApiClientTests.kt +++ b/identity/src/test/java/io/falu/identity/api/IdentityVerificationApiClientTests.kt @@ -18,6 +18,7 @@ import io.falu.identity.api.models.verification.VerificationDocumentUpload import io.falu.identity.api.models.verification.VerificationModel import io.falu.identity.api.models.verification.VerificationOptions import io.falu.identity.api.models.verification.VerificationOptionsForDocument +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationStatus import io.falu.identity.api.models.verification.VerificationType import io.falu.identity.api.models.verification.VerificationUploadRequest @@ -31,7 +32,6 @@ import org.mockito.kotlin.whenever import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config import software.tingle.api.ResourceResponse -import software.tingle.api.patch.JsonPatchDocument import java.io.File import java.util.Date import kotlin.test.BeforeTest @@ -111,7 +111,7 @@ class IdentityVerificationApiClientTests { fun `test if updating verification works`() { mockWebServer.url("$BASE_URL/v1/identity/verifications/${verification.id}/workflow") - val document = JsonPatchDocument().replace("/test", "test") + val document = VerificationUpdateOptions(consent = true) val resourceResponse = getResponse(tResponse = verification) whenever(apiClient.updateVerification(verification.id, document)) @@ -121,7 +121,7 @@ class IdentityVerificationApiClientTests { val response = apiClient.updateVerification(verification.id, document) assertNotNull(response.resource) - assertEquals(response.resource!!.id, verification.id) + assertEquals(response.resource?.id.orEmpty(), verification.id) } @Test