Skip to content

Commit

Permalink
Merge pull request #150 from velocitycareerlabs/VL-8490
Browse files Browse the repository at this point in the history
VL-8490 - v2.6.9 support primary-source checks using @context
  • Loading branch information
michaelavoyan authored Dec 1, 2024
2 parents a0e282b + 8e9196b commit be38f59
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 51 deletions.
4 changes: 2 additions & 2 deletions VCL/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
defaultConfig {
minSdk 24
targetSdk 34
versionName "2.6.8"
versionCode 152
versionName "2.6.9"
versionCode 153
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,8 @@ package io.velocitycareerlabs.impl.data.repositories
import io.velocitycareerlabs.api.entities.*
import io.velocitycareerlabs.api.entities.error.VCLError
import io.velocitycareerlabs.impl.data.infrastructure.network.Request
import io.velocitycareerlabs.impl.data.infrastructure.network.Response
import io.velocitycareerlabs.impl.data.utils.Utils
import io.velocitycareerlabs.impl.domain.infrastructure.network.NetworkService
import io.velocitycareerlabs.impl.domain.repositories.GenerateOffersRepository
import io.velocitycareerlabs.impl.extensions.toJsonArray
import io.velocitycareerlabs.impl.extensions.toJsonObject
import org.json.JSONArray
import org.json.JSONObject
import java.lang.Exception

internal class GenerateOffersRepositoryImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import io.velocitycareerlabs.api.entities.handleResult
import io.velocitycareerlabs.impl.data.infrastructure.network.Request
import io.velocitycareerlabs.impl.data.repositories.HeaderKeys
import io.velocitycareerlabs.impl.data.repositories.HeaderValues
import io.velocitycareerlabs.impl.data.utils.Utils
import io.velocitycareerlabs.impl.domain.infrastructure.network.NetworkService
import io.velocitycareerlabs.impl.domain.models.CredentialTypesModel
import io.velocitycareerlabs.impl.domain.verifiers.CredentialIssuerVerifier
Expand Down Expand Up @@ -47,7 +46,7 @@ internal class CredentialIssuerVerifierImpl(
var globalError: VCLError? = null
val completableFutures = jwtCredentials.map { jwtCredential ->
CompletableFuture.supplyAsync {
Utils.getCredentialType(jwtCredential)?.let { credentialTypeName ->
VerificationUtils.getCredentialType(jwtCredential)?.let { credentialTypeName ->
credentialTypesModel.credentialTypeByTypeName(credentialTypeName)
?.let { credentialType ->
verifyCredential(
Expand Down Expand Up @@ -138,11 +137,11 @@ internal class CredentialIssuerVerifierImpl(
if (permittedServiceCategory.contains(VCLServiceType.NotaryIssuer)) {
completionBlock(VCLResult.Success(true))
} else if (permittedServiceCategory.contains(VCLServiceType.Issuer)) {
Utils.getCredentialSubject(jwtCredential)?.let { credentialSubject ->
retrieveContextFromCredentialSubject(credentialSubject)?.let { credentialSubjectContexts ->
resolveCredentialSubjectContexts(credentialSubjectContexts) { credentialSubjectContextsResult ->
credentialSubjectContextsResult.handleResult({ completeContexts ->
onResolveCredentialSubjectContexts(
VerificationUtils.getCredentialSubjectFromCredential(jwtCredential)?.let { credentialSubject ->
VerificationUtils.getContextsFromCredential(jwtCredential)?.let { credentialContexts ->
resolveCredentialContexts(credentialContexts) { credentialContextsResult ->
credentialContextsResult.handleResult({ completeContexts ->
onResolveCredentialContexts(
credentialSubject,
jwtCredential,
completeContexts,
Expand Down Expand Up @@ -178,17 +177,7 @@ internal class CredentialIssuerVerifierImpl(
}
}

private fun retrieveContextFromCredentialSubject(credentialSubject: Map<*, *>): List<*>? {
(credentialSubject[KeyContext] as? List<*>)?.let { credentialSubjectContexts ->
return credentialSubjectContexts
}
(credentialSubject[KeyContext] as? String)?.let { credentialSubjectContext ->
return listOf(credentialSubjectContext)
}
return null
}

private fun resolveCredentialSubjectContexts(
private fun resolveCredentialContexts(
credentialSubjectContexts: List<*>,
completionBlock: (VCLResult<List<Map<*, *>>>) -> Unit
) {
Expand Down Expand Up @@ -234,7 +223,7 @@ internal class CredentialIssuerVerifierImpl(
}
}

private fun onResolveCredentialSubjectContexts(
private fun onResolveCredentialContexts(
credentialSubject: Map<*, *>,
jwtCredential: VCLJwt,
completeContexts: List<Map<*, *>>,
Expand All @@ -249,12 +238,12 @@ internal class CredentialIssuerVerifierImpl(
?.get(KeyContext) as? Map<*, *>
?: completeContext
findKeyForPrimaryOrganizationValue(activeContext)?.let { K ->
Utils.getIdentifier(K, credentialSubject)?.let { did ->
VerificationUtils.getIdentifier(K, credentialSubject)?.let { did ->
// Comparing issuer.id instead of iss
// https://velocitycareerlabs.atlassian.net/browse/VL-6178?focusedCommentId=46933
// https://velocitycareerlabs.atlassian.net/browse/VL-6988
// if (jwtCredential.iss == did)
val credentialIssuerId = Utils.getCredentialIssuerId(jwtCredential)
val credentialIssuerId = VerificationUtils.getCredentialIssuerId(jwtCredential)
VCLLog.d(
TAG,
"Comparing credentialIssuerId: ${credentialIssuerId ?: ""} with did: $did"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,58 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.velocitycareerlabs.impl.data.utils
package io.velocitycareerlabs.impl.data.verifiers

import io.velocitycareerlabs.api.entities.VCLJwt
import io.velocitycareerlabs.api.entities.VCLOffer
import io.velocitycareerlabs.impl.data.verifiers.CredentialIssuerVerifierImpl
import org.json.JSONArray
import io.velocitycareerlabs.impl.data.verifiers.CredentialIssuerVerifierImpl.CodingKeys.KeyContext

internal class Utils {
internal class VerificationUtils {
companion object {
internal fun getCredentialType(jwtCredential: VCLJwt): String? =
((jwtCredential.payload?.toJSONObject()
?.get(CredentialIssuerVerifierImpl.KeyVC) as? Map<*, *>)
?.get(CredentialIssuerVerifierImpl.KeyType) as? List<*>)
?.first() as? String

internal fun getCredentialSubject(jwtCredential: VCLJwt): Map<*, *>? =
(jwtCredential.payload?.toJSONObject()
internal fun getCredentialSubjectFromCredential(jwtCredential: VCLJwt): Map<*, *>? =
getCredentialSubjectFromPayload(jwtCredential.payload?.toJSONObject())

internal fun getContextsFromCredential(jwtCredential: VCLJwt): List<*>? {
val credentialPayloadJson = jwtCredential.payload?.toJSONObject()

val rootContextsList =
getContextsFromPayload(credentialPayloadJson?.get(CredentialIssuerVerifierImpl.KeyVC) as? Map<*, *>)
val credentialSubjectContextsList =
getContextsFromPayload(getCredentialSubjectFromPayload(credentialPayloadJson))

return if (rootContextsList == null && credentialSubjectContextsList == null) {
null
} else {
(rootContextsList ?: emptyList<Map<*, *>>())
.union(credentialSubjectContextsList ?: emptyList()).toList()
}
}

private fun getCredentialSubjectFromPayload(credentialPayload: Map<*, *>?): Map<*, *>? =
(credentialPayload
?.get(CredentialIssuerVerifierImpl.KeyVC) as? Map<*, *>)
?.get(CredentialIssuerVerifierImpl.KeyCredentialSubject) as? Map<*, *>

private fun getContextsFromPayload(map: Map<*, *>?): List<*>? {
(map?.get(KeyContext) as? List<*>)?.let { credentialSubjectContexts ->
return credentialSubjectContexts
}
(map?.get(KeyContext) as? String)?.let { credentialSubjectContext ->
return listOf(credentialSubjectContext)
}
return null
}

internal fun getIdentifier(
primaryOrgProp: String?,
jsonObject: Map<*, *>
): String? {
if(primaryOrgProp == null) {
if (primaryOrgProp == null) {
return null
}
var identifier: String? = null
Expand Down Expand Up @@ -83,7 +110,7 @@ internal class Utils {
?: (credentialSubject as? Map<*, *>)?.get("id") as? String
}

fun getCredentialIssuerId(jwtCredential: VCLJwt): String? {
internal fun getCredentialIssuerId(jwtCredential: VCLJwt): String? {
val vc: Map<*, *>? = jwtCredential.payload?.toJSONObject()?.get("vc") as? Map<*, *>
return (vc?.get("issuer") as? Map<*, *>)?.get("id") as? String
?: vc?.get("issuer") as? String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

package io.velocitycareerlabs.utils

import io.velocitycareerlabs.impl.data.utils.Utils
import io.velocitycareerlabs.impl.data.verifiers.VerificationUtils
import org.junit.Test

class UtilsTest {
class VerificationUtilsTest {
@Test
fun testGetIdentifier() {
val jsonObject = mapOf(
Expand All @@ -22,7 +22,7 @@ class UtilsTest {
)

val primaryOrgProp = "id"
val result = Utils.getIdentifier(primaryOrgProp, jsonObject)
val result = VerificationUtils.getIdentifier(primaryOrgProp, jsonObject)

// assert("ValueC" == result) // what about this case?
assert("ValueD" == result) // because of stack
Expand All @@ -37,39 +37,39 @@ class UtilsTest {
)

val primaryOrgProp = "id"
val result = Utils.getIdentifier(primaryOrgProp, jsonObject)
val result = VerificationUtils.getIdentifier(primaryOrgProp, jsonObject)

assert(result == null)
}

@Test
fun testGetPrimaryIdentifier() {
val value = "ValueX"
val result = Utils.getPrimaryIdentifier(value)
val result = VerificationUtils.getPrimaryIdentifier(value)

assert("ValueX" == result)
}

@Test
fun testGetPrimaryIdentifier_MapWithId() {
val value = mapOf("id" to "ValueY")
val result = Utils.getPrimaryIdentifier(value)
val result = VerificationUtils.getPrimaryIdentifier(value)

assert("ValueY" == result)
}

@Test
fun testGetPrimaryIdentifier_MapWithIdentifier() {
val value = mapOf("identifier" to "ValueZ")
val result = Utils.getPrimaryIdentifier(value)
val result = VerificationUtils.getPrimaryIdentifier(value)

assert("ValueZ" == result)
}

@Test
fun testGetPrimaryIdentifier_Null() {
val value: Map<*, *>? = null
val result = Utils.getPrimaryIdentifier(value)
val result = VerificationUtils.getPrimaryIdentifier(value)

assert(result == null)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,10 @@ internal class CredentialIssuerVerifierTest {
) { verificationResult ->
verificationResult.handleResult(
successHandler = {
assert(false) { "${VCLErrorCode.InvalidCredentialSubjectContext.value} error code is expected" }
assert(false) { "${VCLErrorCode.InvalidCredentialSubjectType.value} error code is expected" }
},
errorHandler = { error ->
assert(error.errorCode == VCLErrorCode.InvalidCredentialSubjectContext.value)
assert(error.errorCode == VCLErrorCode.InvalidCredentialSubjectType.value)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
package io.velocitycareerlabs.verifiers

import io.velocitycareerlabs.api.entities.VCLDeepLink
import io.velocitycareerlabs.api.entities.VCLOffer
import io.velocitycareerlabs.api.entities.VCLOffers
import io.velocitycareerlabs.api.entities.VCLToken
import io.velocitycareerlabs.api.entities.error.VCLErrorCode
import io.velocitycareerlabs.api.entities.handleResult
import io.velocitycareerlabs.impl.data.utils.Utils
import io.velocitycareerlabs.impl.data.verifiers.OffersByDeepLinkVerifierImpl
import io.velocitycareerlabs.impl.extensions.toJsonObject
import io.velocitycareerlabs.infrastructure.resources.valid.DeepLinkMocks
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.7.1'
classpath 'com.android.tools.build:gradle:8.7.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
Expand Down

0 comments on commit be38f59

Please sign in to comment.