Skip to content

Commit d2d35ff

Browse files
authored
Merge pull request #272 from walt-id/verificatio-policy-result-result-pattern
refactor: verification-policy-result implement operation-result-pattern
2 parents 0c7d120 + 3b3ce9c commit d2d35ff

13 files changed

+72
-66
lines changed

.github/workflows/build.yml

+17-16
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,20 @@ jobs:
4646
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
4747
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
4848
with:
49-
arguments: build publish --no-daemon
50-
- name: Docker Build and Push SNAPSHOT
51-
uses: philpotisk/github-action-docker-build-push@master
52-
env:
53-
DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}}
54-
DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}}
55-
DOCKER_FILE: Dockerfile
56-
CONTAINER_TAG: waltid/ssikit:latest
57-
- name: Prepare CD K8S
58-
run: sed "s/_DEFAULT_DEPLOYMENT_/$GITHUB_SHA/g" k8s/deployment-dev.yaml > k8s/deployment-dev_mod.yaml
59-
- name: Continuous deployment K8S
60-
uses: actions-hub/kubectl@master
61-
env:
62-
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
63-
with:
64-
args: apply -n dev -f k8s/deployment-dev_mod.yaml
49+
arguments: build --no-daemon
50+
# arguments: build publish --no-daemon
51+
# - name: Docker Build and Push SNAPSHOT
52+
# uses: philpotisk/github-action-docker-build-push@master
53+
# env:
54+
# DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}}
55+
# DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}}
56+
# DOCKER_FILE: Dockerfile
57+
# CONTAINER_TAG: waltid/ssikit:latest
58+
# - name: Prepare CD K8S
59+
# run: sed "s/_DEFAULT_DEPLOYMENT_/$GITHUB_SHA/g" k8s/deployment-dev.yaml > k8s/deployment-dev_mod.yaml
60+
# - name: Continuous deployment K8S
61+
# uses: actions-hub/kubectl@master
62+
# env:
63+
# KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
64+
# with:
65+
# args: apply -n dev -f k8s/deployment-dev_mod.yaml

src/main/kotlin/id/walt/auditor/Auditor.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,18 @@ class WaltIdAuditor : Auditor() {
4141
log.debug { "Verifying vc with ${policy.id} ..." }
4242

4343
val vcResult = policy.verify(vc)
44-
val success = AtomicBoolean(vcResult.result)
44+
val success = AtomicBoolean(vcResult.isSuccess)
4545
val allErrors = vcResult.errors.toMutableList()
4646
if (allErrors.isEmpty() && vc is VerifiablePresentation) {
4747
vc.verifiableCredential?.forEach { cred ->
4848
log.debug { "Verifying ${cred.type.last()} in VP with ${policy.id}..." }
4949
val vpResult = policy.verify(cred)
5050
allErrors.addAll(vpResult.errors)
51-
success.compareAndSet(true, vpResult.result)
51+
success.compareAndSet(true, vpResult.isSuccess)
5252
}
5353
}
5454
allErrors.forEach { log.error { "${policy.id}: $it" } }
55-
VerificationPolicyResult(success.get(), allErrors)
55+
success.get().takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure(*allErrors.toTypedArray())
5656
}
5757

5858
return VerificationResult(allAccepted(policyResults), policyResults)

src/main/kotlin/id/walt/auditor/VerificationPolicy.kt

+12-7
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,26 @@ data class VerificationPolicyMetadata(
5656
val isMutable: Boolean
5757
)
5858

59-
data class VerificationPolicyResult(val result: Boolean, @JsonIgnore val errors: List<Throwable> = listOf()) {
59+
class VerificationPolicyResult private constructor(
60+
private val result: Boolean,
61+
@JsonIgnore
62+
private val errorList: List<Throwable> = emptyList()
63+
) {
64+
6065
companion object {
6166
fun success() = VerificationPolicyResult(true)
62-
fun failure(error: Throwable): VerificationPolicyResult {
63-
log.debug { "VerificationPolicy failed: ${error.stackTraceToString()}" }
64-
return VerificationPolicyResult(false, listOf(error))
67+
fun failure(vararg error: Throwable): VerificationPolicyResult {
68+
log.debug { "VerificationPolicy failed: ${error.joinToString { it.localizedMessage }}" }
69+
return VerificationPolicyResult(false, error.asList())
6570
}
66-
67-
fun failure(errors: List<Throwable> = listOf()) = VerificationPolicyResult(false, errors.toList())
6871
}
6972

7073
val isSuccess = result
7174
val isFailure = !result
75+
@JsonIgnore
76+
val errors = errorList
7277

73-
fun getErrorString() = errors.mapIndexed { index, throwable ->
78+
private fun getErrorString() = errorList.mapIndexed { index, throwable ->
7479
"#${index + 1}: ${throwable::class.simpleName ?: "Error"} - ${throwable.message}"
7580
}.joinToString()
7681

src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
package id.walt.auditor.dynamic
22

3-
import com.beust.klaxon.JsonObject
43
import com.beust.klaxon.Klaxon
5-
import com.beust.klaxon.Parser
64
import id.walt.auditor.VerificationPolicyResult
75
import id.walt.common.resolveContentToFile
8-
import id.walt.credentials.w3c.JsonConverter
9-
import kotlinx.serialization.json.buildJsonObject
106
import mu.KotlinLogging
11-
import java.io.File
127

138
object OPAPolicyEngine : PolicyEngine {
149
private val log = KotlinLogging.logger {}
@@ -37,7 +32,8 @@ object OPAPolicyEngine : PolicyEngine {
3732
val output = p.inputStream.reader().use { it.readText() }
3833
p.waitFor()
3934
log.debug("rego eval output: {}", output)
40-
return VerificationPolicyResult(Klaxon().parseArray<Boolean>(output)?.all { it } ?: false)
35+
return (Klaxon().parseArray<Boolean>(output)?.all { it } ?: false).takeIf { it }
36+
?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
4137
} finally {
4238
if (regoFile.exists() && regoFile.name.startsWith(TEMP_PREFIX)) {
4339
regoFile.delete()

src/main/kotlin/id/walt/auditor/policies/CredentialPropertyVerificationPolicies.kt

+8-7
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,30 @@ private val dateFormatter =
1818
class IssuedDateBeforePolicy : SimpleVerificationPolicy() {
1919
override val description: String = "Verify by issuance date"
2020
override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult {
21-
return VerificationPolicyResult(when (vc) {
21+
return when (vc) {
2222
is VerifiablePresentation -> true
2323
else -> parseDate(vc.issued).let { it != null && it.before(Date()) }
24-
})
24+
}.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
2525
}
2626
}
2727

2828
class ValidFromBeforePolicy : SimpleVerificationPolicy() {
2929
override val description: String = "Verify by valid from"
3030
override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult {
31-
return VerificationPolicyResult(when (vc) {
31+
return when (vc) {
3232
is VerifiablePresentation -> true
3333
else -> parseDate(vc.validFrom).let { it != null && it.before(Date()) }
34-
})
34+
}.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
3535
}
3636
}
3737

3838
class ExpirationDateAfterPolicy : SimpleVerificationPolicy() {
3939
override val description: String = "Verify by expiration date"
4040
override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult {
41-
return VerificationPolicyResult(when (vc) {
41+
return when (vc) {
4242
is VerifiablePresentation -> true
4343
else -> parseDate(vc.expirationDate).let { it == null || it.after(Date()) }
44-
})
44+
}.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
4545
}
4646
}
4747

@@ -92,7 +92,8 @@ class ChallengePolicy(challengeArg: ChallengePolicyArg) :
9292

9393
override val description: String = "Verify challenge"
9494
override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult {
95-
return VerificationPolicyResult(vc.challenge?.let { argument.challenges.contains(it) } ?: false)
95+
return (vc.challenge?.let { argument.challenges.contains(it) } ?: false).takeIf { it }
96+
?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
9697
}
9798

9899
override val applyToVC: Boolean

src/main/kotlin/id/walt/auditor/policies/EbsiVerificationPolicies.kt

+4-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class EbsiTrustedIssuerDidPolicy : SimpleVerificationPolicy() {
5252
override val description: String = "Verify by trusted issuer did"
5353
override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult {
5454
return try {
55-
VerificationPolicyResult(DidService.loadOrResolveAnyDid(vc.issuerId!!) != null)
55+
DidService.loadOrResolveAnyDid(vc.issuerId!!)?.let { VerificationPolicyResult.success() }
56+
?: VerificationPolicyResult.failure()
5657
} catch (e: ClientRequestException) {
5758
VerificationPolicyResult.failure(
5859
IllegalArgumentException(
@@ -147,15 +148,15 @@ class EbsiTrustedIssuerRegistryPolicy(registryArg: EbsiTrustedIssuerRegistryPoli
147148
class EbsiTrustedSubjectDidPolicy : SimpleVerificationPolicy() {
148149
override val description: String = "Verify by trusted subject did"
149150
override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult {
150-
return VerificationPolicyResult(vc.subjectId?.let {
151+
return (vc.subjectId?.let {
151152
if (it.isEmpty()) true
152153
else try {
153154
DidService.loadOrResolveAnyDid(it) != null
154155
} catch (e: ClientRequestException) {
155156
if (!e.message.contains("did must be a valid DID") && !e.message.contains("Identifier Not Found")) throw e
156157
false
157158
}
158-
} ?: false)
159+
} ?: false).takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
159160
}
160161
}
161162

src/main/kotlin/id/walt/auditor/policies/SignaturePolicy.kt

+4-6
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ class SignaturePolicy : SimpleVerificationPolicy() {
1616

1717
override fun doVerify(vc: VerifiableCredential) = runCatching {
1818
log.debug { "is jwt: ${vc.jwt != null}" }
19-
VerificationPolicyResult(
20-
vc.verifyByFormatType(
21-
{ jwtCredentialService.verify(it) },
22-
{ jsonLdCredentialService.verify(it) }
23-
).verified
24-
)
19+
vc.verifyByFormatType(
20+
{ jwtCredentialService.verify(it) },
21+
{ jsonLdCredentialService.verify(it) }
22+
).verified.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
2523
}.getOrElse {
2624
VerificationPolicyResult.failure(it)
2725
}

src/main/kotlin/id/walt/auditor/policies/VerifiablePresentationsPolicies.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ class PresentationDefinitionPolicy(presentationDefinition: PresentationDefinitio
1111
ParameterizedVerificationPolicy<PresentationDefinition>(presentationDefinition) {
1212
override val description: String = "Verify that verifiable presentation complies with presentation definition"
1313
override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult {
14-
return VerificationPolicyResult(if (vc is VerifiablePresentation) {
14+
return (if (vc is VerifiablePresentation) {
1515
argument.input_descriptors.all { desc ->
1616
vc.verifiableCredential?.any { cred -> OIDCUtils.matchesInputDescriptor(cred, desc) } ?: false
1717
}
18-
} else false)
18+
} else false).takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure()
1919
}
2020

2121
override var applyToVC: Boolean = false

src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class NetworkntSchemaValidator(versionFlag: SpecVersion.VersionFlag, schema: Str
1919
log.debug { "Could not validate vc against schema. The validation errors are:" }
2020
errors.forEach { log.debug { it } }
2121
}
22-
return VerificationPolicyResult(errors.isEmpty(), errors.map { SchemaViolationException(it.toString()) })
22+
return errors.takeIf { it.isEmpty() }?.let {
23+
VerificationPolicyResult.success()
24+
} ?: VerificationPolicyResult.failure(*errors.map { SchemaViolationException(it.toString()) }.toTypedArray())
2325
}
2426
}

src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ class PWallSchemaValidator(schema: String) : SchemaValidator {
1616
log.debug { "Could not validate vc against schema. The validation errors are:" }
1717
errors.forEach { log.debug { it } }
1818
}
19-
return VerificationPolicyResult(errors.isEmpty(), errors.map {
20-
SchemaViolationException(it.error)
21-
})
19+
return errors.takeIf { it.isEmpty() }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure(
20+
*errors.map {
21+
SchemaViolationException(it.error)
22+
}.toTypedArray()
23+
)
2224
}
2325
}

src/test/kotlin/id/walt/auditor/AuditorTest.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class AuditorCommandTest : StringSpec() {
9393

9494
res.policyResults.keys shouldContainAll policyList.map { it.id }
9595

96-
res.policyResults.values.forEach { it.result shouldBe true }
96+
res.policyResults.values.forEach { it.isSuccess shouldBe true }
9797
}
9898

9999
"2. verify vc" {
@@ -107,7 +107,7 @@ class AuditorCommandTest : StringSpec() {
107107

108108
res.policyResults.keys shouldContainAll listOf(SignaturePolicy()).map { it.id }
109109

110-
res.policyResults.values.forEach { it.result shouldBe true }
110+
res.policyResults.values.forEach { it.isSuccess shouldBe true }
111111
}
112112

113113
"3. verify vc jwt" {
@@ -121,7 +121,7 @@ class AuditorCommandTest : StringSpec() {
121121

122122
res.policyResults.keys shouldContainAll listOf(SignaturePolicy()).map { it.id }
123123

124-
res.policyResults.values.forEach { it.result shouldBe true }
124+
res.policyResults.values.forEach { it.isSuccess shouldBe true }
125125
}
126126

127127
"4. verify vp jwt" {
@@ -136,7 +136,7 @@ class AuditorCommandTest : StringSpec() {
136136

137137
res.policyResults.keys shouldContainAll listOf(SignaturePolicy()).map { it.id }
138138

139-
res.policyResults.values.forEach { it.result shouldBe true }
139+
res.policyResults.values.forEach { it.isSuccess shouldBe true }
140140
}
141141

142142
// CLI call for testing VerifiableMandatePolicy

src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,10 @@ class WaltIdJsonLdCredentialServiceTest : AnnotationSpec() {
234234
)
235235
val notParsableVc = ""
236236

237-
credentialService.validateSchemaTsr(noSchemaVc).result shouldBe false
238-
credentialService.validateSchemaTsr(validVc).result shouldBe true
239-
credentialService.validateSchemaTsr(invalidDataVc).result shouldBe false
240-
credentialService.validateSchemaTsr(notParsableVc).result shouldBe false
237+
credentialService.validateSchemaTsr(noSchemaVc).isSuccess shouldBe false
238+
credentialService.validateSchemaTsr(validVc).isSuccess shouldBe true
239+
credentialService.validateSchemaTsr(invalidDataVc).isSuccess shouldBe false
240+
credentialService.validateSchemaTsr(notParsableVc).isSuccess shouldBe false
241241
}
242242

243243
/*@Test

src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ class WaltIdJwtCredentialServiceTest : AnnotationSpec() {
142142
)
143143
val notParsableVc = ""
144144

145-
credentialService.validateSchemaTsr(noSchemaVc).result shouldBe true
146-
credentialService.validateSchemaTsr(validVc).result shouldBe true
147-
credentialService.validateSchemaTsr(invalidDataVc).result shouldBe false
148-
credentialService.validateSchemaTsr(notParsableVc).result shouldBe false
145+
credentialService.validateSchemaTsr(noSchemaVc).isSuccess shouldBe true
146+
credentialService.validateSchemaTsr(validVc).isSuccess shouldBe true
147+
credentialService.validateSchemaTsr(invalidDataVc).isSuccess shouldBe false
148+
credentialService.validateSchemaTsr(notParsableVc).isSuccess shouldBe false
149149
}
150150

151151
@Test

0 commit comments

Comments
 (0)