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

refactor: Serialization of Verifiable Credential with extended data model #564

Merged
merged 1 commit into from
Oct 25, 2019

Conversation

kdimak
Copy link
Contributor

@kdimak kdimak commented Oct 23, 2019

closes #327

Signed-off-by: Dima [email protected]

This PR brings the following improvements to the Verifiable Credential (VC):

  • Keep extra fields of raw VC in a map (motivated by issue 22533); this leverages the extensibility of the data model and allows more strict serialization of the VC.
  • Use stricter types in Credential: issuer, context, type (used generic interface{} or []interface{} before).
  • Simplify JWT decoding. Previously, JWT decoding resulted in returning *rawCredential and serialized JSON ([]byte) of VC. Now it returns only serialized JSON which is then unmarshalled to rawCredential.

@codecov
Copy link

codecov bot commented Oct 23, 2019

Codecov Report

Merging #564 into master will decrease coverage by 0.2%.
The diff coverage is 87.43%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #564      +/-   ##
==========================================
- Coverage   90.48%   90.28%   -0.21%     
==========================================
  Files          77       77              
  Lines        4235     4302      +67     
==========================================
+ Hits         3832     3884      +52     
- Misses        223      231       +8     
- Partials      180      187       +7
Impacted Files Coverage Δ
pkg/doc/verifiable/credential_jws.go 100% <100%> (ø) ⬆️
pkg/doc/verifiable/common.go 100% <100%> (ø) ⬆️
pkg/doc/verifiable/credential_jwt_unsecured.go 100% <100%> (ø) ⬆️
pkg/doc/verifiable/credential.go 87.87% <85.53%> (-4.03%) ⬇️
pkg/doc/verifiable/credential_jwt.go 90.47% <90.32%> (+4.36%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c086c6b...c446183. Read the comment docs.

if err != nil {
return nil, nil, fmt.Errorf("failed to decode raw Verifiable Credential JWT claims: %w", err)
return nil, fmt.Errorf("failed to decode Verifiable Credential JWT claims: %w", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree! I think it deserves the creation of a separate issue, to clean-up the whole credential package.
#570

@troyronda
Copy link
Contributor

This PR/commit appears to be a "refactor: " rather than a "feat: "

@kdimak
Copy link
Contributor Author

kdimak commented Oct 23, 2019

@troyronda yes, this is definitely "refactor:".

@kdimak kdimak changed the title feat: Serialization of Verifiable Credential with extended data model refactor: Serialization of Verifiable Credential with extended data model Oct 24, 2019
Comment on lines +449 to +472
func decodeType(rc *rawCredential) ([]string, error) {
switch rType := rc.Type.(type) {
case string:
return []string{rType}, nil
case []interface{}:
types, err := stringSlice(rType)
if err != nil {
return nil, fmt.Errorf("failed to map credential types: %w", err)
}
return types, nil
default:
return nil, errors.New("credential type of unknown type")
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like this approach with different types string and []interface{}, are we able to change this logic? We can use comma-separated values instead of different types e.g type1 or type1,type3,... or only slice [type1] or [type1,type2]
@troyronda @rolsonquadras @fqutishat

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @soluchok
According to Verifiable Credentials spec, the type can be defined as either a single string value or array. We keep it raw in rawCredential struct (into which VC JSON is unmarshalled) and then decode it to universal and convenient []string to be used in Credential struct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would, at least, add some comments in the code. It isn’t entirely clear to a reader when they see these case statements.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -63,7 +64,7 @@ type typedID struct {
type RefreshService typedID

// TermsOfUse represents terms of use of Verifiable Credential by Issuer or Verifiable Presentation by Holder.
type TermsOfUse typedID
type TermsOfUse interface{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too excited when we need to export types/struct that have interface{}

Can you give more context on this change?

Copy link
Contributor Author

@kdimak kdimak Oct 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was incorrectly defined before. It can be one or more TermsOfUse. Its structure is not precisely defined. They say that type field is mandatory and id field is optional, and

The precise contents of each term of use is determined by the specific termsOfUse type definition.

If we use typedID alias for termsOfUse and after decoding of VC want to marshal it back, we will loose all the original fields except type and id.
That was the reason I changed the TermsOfUse alias.
We can also stay with typedID alias and extend it to keep all extra fields in e.g. map[string]interface{} to be used during marshalling.
What do you think @troyronda?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we had typically used an unexported "raw" struct and filled a properly typed exported struct.

Copy link
Contributor

@troyronda troyronda Oct 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. It's another situation with extended fields. I would think you would have defined the known parts and keep extra fields in map[string]interface{} like you did elsewhere in the PR.

Is it because it is "one or more"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because of "one or more" and also because of the flexible structure of the termsOfUse field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed a separate issue #586.

nbfTime := nbf.Time().UTC()
raw.Issued = &nbfTime
vcMap["issuanceDate"] = nbfTime.Format(time.RFC3339)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some of these strings could make sense as named constants.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree! Done.

@troyronda troyronda merged commit b836776 into hyperledger-archives:master Oct 25, 2019
@kdimak kdimak deleted the issue-327 branch October 25, 2019 14:15
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Marshalling of Verifiable Credential with extended data model
3 participants