Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
Fixing Cred Suspension Bug (#487)
Browse files Browse the repository at this point in the history
* fixing bug

* updates

* small fixes

* updated to use json template
  • Loading branch information
nitro-neal authored May 26, 2023
1 parent 712e224 commit 47db532
Show file tree
Hide file tree
Showing 14 changed files with 449 additions and 47 deletions.
24 changes: 15 additions & 9 deletions integration/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,30 @@ func CreateKYCSchema() (string, error) {
}

type credInputParams struct {
IssuerID string
IssuerKID string
SchemaID string
SubjectID string
IssuerID string
IssuerKID string
SchemaID string
SubjectID string
Revocable bool
Suspendable bool
}

func CreateVerifiableCredential(credentialInput credInputParams, revocable bool) (string, error) {
func CreateVerifiableCredential(credentialInput credInputParams) (string, error) {
logrus.Println("\n\nCreate a verifiable credential")

if credentialInput.SubjectID == "" {
credentialInput.SubjectID = credentialInput.IssuerID
}

fileName := "credential-input.json"
if revocable {
fileName = "credential-revocable-input.json"
if credentialInput.Revocable {
credentialInput.Revocable = true
}
credentialJSON, err := resolveTemplate(credentialInput, fileName)

if credentialInput.Suspendable {
credentialInput.Suspendable = true
}

credentialJSON, err := resolveTemplate(credentialInput, "credential-input.json")
if err != nil {
return "", err
}
Expand Down
2 changes: 1 addition & 1 deletion integration/credential_manifest_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestCreateVerifiableCredentialIntegration(t *testing.T) {
IssuerKID: issuerKID.(string),
SchemaID: schemaID.(string),
SubjectID: issuerDID.(string),
}, false)
})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutput)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestCreateRevocationVerifiableCredentialIntegration(t *testing.T) {
assert.NoError(t, err)
assert.NotEmpty(t, schemaID)

vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID, Revocable: true})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutput)

Expand Down Expand Up @@ -68,7 +68,7 @@ func TestCreateRevocationVerifiableCredentialShareStatusListIntegration(t *testi
assert.NoError(t, err)
assert.NotEmpty(t, schemaID)

vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID, Revocable: true})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutput)

Expand All @@ -82,7 +82,7 @@ func TestCreateRevocationVerifiableCredentialShareStatusListIntegration(t *testi
assert.NotEmpty(t, credStatusListURL)
assert.Contains(t, credStatusListURL, "http")

vcOutputTwo, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
vcOutputTwo, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID, Revocable: true})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutputTwo)

Expand Down Expand Up @@ -135,7 +135,7 @@ func TestConcurrencyRevocationVerifiableCredentialIntegration(t *testing.T) {
go func() {
defer wg.Done()

vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID, Revocable: true})

// We're hammering the DB, so some calls might fail due to internal timeouts or similar. Upon failure, we
// shouldn't check any assertions, since we know they'll fail.
Expand Down
36 changes: 35 additions & 1 deletion integration/credential_revocation_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ func TestRevocationCreateVerifiableCredentialIntegration(t *testing.T) {
IssuerKID: issuerKID.(string),
SchemaID: schemaID.(string),
SubjectID: issuerDID.(string),
}, true)
Revocable: true,
})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutput)

Expand Down Expand Up @@ -195,3 +196,36 @@ func TestRevocationValidateCredentialInStatusListIntegration(t *testing.T) {
assert.NoError(t, err)
assert.True(t, valid)
}

func TestRevocationUnRevokeCredential(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

credStatusURL, err := GetValue(credentialRevocationContext, "credStatusURL")
assert.NoError(t, err)
assert.NotEmpty(t, credStatusURL)

credStatusOutput, err := get(credStatusURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusOutput)

revoked, err := getJSONElement(credStatusOutput, "$.revoked")
assert.NoError(t, err)
assert.Equal(t, "true", revoked)

revokedOutput, err := put(credStatusURL.(string), `{"revoked":false}`)
assert.NoError(t, err)

revoked, err = getJSONElement(revokedOutput, "$.revoked")
assert.NoError(t, err)
assert.Equal(t, "false", revoked)

credStatusOutput, err = get(credStatusURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusOutput)

revoked, err = getJSONElement(credStatusOutput, "$.revoked")
assert.NoError(t, err)
assert.Equal(t, "false", revoked)
}
234 changes: 234 additions & 0 deletions integration/credential_suspension_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package integration

import (
"fmt"
"testing"

"github.com/TBD54566975/ssi-sdk/credential"
"github.com/TBD54566975/ssi-sdk/credential/status"
"github.com/goccy/go-json"
"github.com/stretchr/testify/assert"
)

var credentialSuspensionContext = NewTestContext("CredentialSuspension")

func TestSuspensionCreateIssuerDIDKeyIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

didKeyOutput, err := CreateDIDKey()
assert.NoError(t, err)

issuerDID, err := getJSONElement(didKeyOutput, "$.did.id")
assert.NoError(t, err)
assert.Contains(t, issuerDID, "did:key")
SetValue(credentialSuspensionContext, "issuerDID", issuerDID)

issuerKID, err := getJSONElement(didKeyOutput, "$.did.verificationMethod[0].id")
assert.NoError(t, err)
assert.NotEmpty(t, issuerKID)
SetValue(credentialSuspensionContext, "issuerKID", issuerKID)
}

func TestSuspensionCreateSchemaIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

output, err := CreateKYCSchema()
assert.NoError(t, err)

schemaID, err := getJSONElement(output, "$.id")
assert.NoError(t, err)
assert.NotEmpty(t, schemaID)
SetValue(credentialSuspensionContext, "schemaID", schemaID)
}

func TestSuspensionCreateVerifiableCredentialIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

issuerDID, err := GetValue(credentialSuspensionContext, "issuerDID")
assert.NoError(t, err)
assert.NotEmpty(t, issuerDID)

issuerKID, err := GetValue(credentialSuspensionContext, "issuerKID")
assert.NoError(t, err)
assert.NotEmpty(t, issuerKID)

schemaID, err := GetValue(credentialSuspensionContext, "schemaID")
assert.NoError(t, err)
assert.NotEmpty(t, schemaID)

vcOutput, err := CreateVerifiableCredential(credInputParams{
IssuerID: issuerDID.(string),
IssuerKID: issuerKID.(string),
SchemaID: schemaID.(string),
SubjectID: issuerDID.(string),
Suspendable: true,
})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutput)

cred, err := getJSONElement(vcOutput, "$.credential")
assert.NoError(t, err)
assert.NotEmpty(t, cred)
SetValue(credentialSuspensionContext, "cred", cred)

credStatusURL, err := getJSONElement(vcOutput, "$.credential.credentialStatus.id")
assert.NoError(t, err)
assert.NotEmpty(t, credStatusURL)
assert.Contains(t, credStatusURL, "http")
SetValue(credentialSuspensionContext, "credStatusURL", credStatusURL)

fmt.Print(credStatusURL)

statusListCredentialURL, err := getJSONElement(vcOutput, "$.credential.credentialStatus.statusListCredential")
assert.NoError(t, err)
assert.NotEmpty(t, statusListCredentialURL)
assert.Contains(t, statusListCredentialURL, "http")
SetValue(credentialSuspensionContext, "statusListCredentialURL", statusListCredentialURL)

credStatusListCredentialOutput, err := get(statusListCredentialURL)
assert.NoError(t, err)
assert.NotEmpty(t, credStatusListCredentialOutput)

encodedListOriginal, err := getJSONElement(credStatusListCredentialOutput, "$.credential.credentialSubject.encodedList")
assert.NoError(t, err)
assert.NotEmpty(t, encodedListOriginal)
SetValue(credentialSuspensionContext, "encodedListOriginal", encodedListOriginal)
}

func TestSuspensionCheckStatusIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

credStatusURL, err := GetValue(credentialSuspensionContext, "credStatusURL")
assert.NoError(t, err)
assert.NotEmpty(t, credStatusURL)

credStatusOutput, err := get(credStatusURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusOutput)

suspended, err := getJSONElement(credStatusOutput, "$.suspended")
assert.NoError(t, err)
assert.Equal(t, "false", suspended)

suspendedOutput, err := put(credStatusURL.(string), getJSONFromFile("suspended-input.json"))
assert.NoError(t, err)

suspended, err = getJSONElement(suspendedOutput, "$.suspended")
assert.NoError(t, err)
assert.Equal(t, "true", suspended)

credStatusOutput, err = get(credStatusURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusOutput)

suspended, err = getJSONElement(credStatusOutput, "$.suspended")
assert.NoError(t, err)
assert.Equal(t, "true", suspended)
}

func TestSuspensionCheckStatusListCredentialIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

statusListCredentialURL, err := GetValue(credentialSuspensionContext, "statusListCredentialURL")
assert.NoError(t, err)
assert.NotEmpty(t, statusListCredentialURL)

credStatusListCredentialOutput, err := get(statusListCredentialURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusListCredentialOutput)

statusListType, err := getJSONElement(credStatusListCredentialOutput, "$.credential.credentialSubject.type")
assert.NoError(t, err)
assert.NotEmpty(t, statusListType)
assert.Equal(t, "StatusList2021", statusListType)

encodedList, err := getJSONElement(credStatusListCredentialOutput, "$.credential.credentialSubject.encodedList")
assert.NoError(t, err)
assert.NotEmpty(t, encodedList)

encodedListOriginal, err := GetValue(credentialSuspensionContext, "encodedListOriginal")
assert.NoError(t, err)
assert.NotEmpty(t, encodedListOriginal)

assert.NotEqual(t, encodedListOriginal.(string), encodedList)
}

func TestSuspensionValidateCredentialInStatusListIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

credJSON, err := GetValue(credentialSuspensionContext, "cred")
assert.NoError(t, err)
assert.NotEmpty(t, credJSON)

var vc credential.VerifiableCredential
err = json.Unmarshal([]byte(credJSON.(string)), &vc)
assert.NoError(t, err)
assert.NotEmpty(t, vc)

statusListCredentialURL, err := GetValue(credentialSuspensionContext, "statusListCredentialURL")
assert.NoError(t, err)
assert.NotEmpty(t, statusListCredentialURL)

credStatusListCredentialOutput, err := get(statusListCredentialURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusListCredentialOutput)

credStatusListCredentialJSON, err := getJSONElement(credStatusListCredentialOutput, "$.credential")
assert.NoError(t, err)
assert.NotEmpty(t, credStatusListCredentialJSON)

var vcStatusList credential.VerifiableCredential
err = json.Unmarshal([]byte(credStatusListCredentialJSON), &vcStatusList)
assert.NoError(t, err)
assert.NotEmpty(t, vcStatusList)

// Validate the StatusListIndex in flipped in the credStatusList
valid, err := status.ValidateCredentialInStatusList(vc, vcStatusList)
assert.NoError(t, err)
assert.True(t, valid)
}

func TestSuspensionUnSuspendCredential(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

credStatusURL, err := GetValue(credentialSuspensionContext, "credStatusURL")
assert.NoError(t, err)
assert.NotEmpty(t, credStatusURL)

credStatusOutput, err := get(credStatusURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusOutput)

suspended, err := getJSONElement(credStatusOutput, "$.suspended")
assert.NoError(t, err)
assert.Equal(t, "true", suspended)

suspendedOutput, err := put(credStatusURL.(string), `{"suspended":false}`)
assert.NoError(t, err)

suspended, err = getJSONElement(suspendedOutput, "$.suspended")
assert.NoError(t, err)
assert.Equal(t, "false", suspended)

credStatusOutput, err = get(credStatusURL.(string))
assert.NoError(t, err)
assert.NotEmpty(t, credStatusOutput)

suspended, err = getJSONElement(credStatusOutput, "$.suspended")
assert.NoError(t, err)
assert.Equal(t, "false", suspended)
}
2 changes: 1 addition & 1 deletion integration/didion_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func TestDIDIONCreateVerifiableCredentialIntegration(t *testing.T) {
IssuerKID: issuerKID.(string),
SchemaID: schemaID.(string),
SubjectID: issuerDID.(string),
}, false)
})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutput)

Expand Down
2 changes: 1 addition & 1 deletion integration/didweb_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestDIDWebCreateVerifiableCredentialIntegration(t *testing.T) {
IssuerKID: issuerKID.(string),
SchemaID: schemaID.(string),
SubjectID: issuerDID.(string),
}, false)
})
assert.NoError(t, err)
assert.NotEmpty(t, vcOutput)

Expand Down
Loading

0 comments on commit 47db532

Please sign in to comment.