Skip to content

Commit

Permalink
feat(sdk): display - support for vc-attachment (#792)
Browse files Browse the repository at this point in the history
Signed-off-by: Rolson Quadras <[email protected]>
  • Loading branch information
rolsonquadras authored Jul 3, 2024
1 parent 5973eb1 commit 9333100
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 21 deletions.
52 changes: 51 additions & 1 deletion cmd/wallet-sdk-gomobile/display/displaydata.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ func (c *Claim) Label() string {
}

// ValueType returns the display value type for this claim.
// For example: "string", "number", "image", etc.
// For example: "string", "number", "image", "attachment" etc.
// For type=attachment, ignore the RawValue() and Value(), instead use Attachment() method.
func (c *Claim) ValueType() string {
return c.claim.ValueType
}
Expand Down Expand Up @@ -287,3 +288,52 @@ func (c *Claim) Order() (int, error) {
func (c *Claim) Locale() string {
return c.claim.Locale
}

// Attachment returns the attachment data. Check this field if the claim type is "attachment", instead of value field.
func (c *Claim) Attachment() *Attachment {
return &Attachment{attachment: c.claim.Attachment}
}

// Attachment represents display data for a credential.
// Display data for specific claims (e.g. first name, date of birth, etc.) are in the CredentialSubject objects.
type Attachment struct {
attachment *goapicredentialschema.Attachment
}

// ID returns the attachment ID.
func (c *Attachment) ID() string {
return c.attachment.ID
}

// Type returns the attachment Type. This could be "EmbeddedAttachment", "RemoteAttachment" or "AttachmentEvidence".
// For EmbeddedAttachment, the uri will be a data URI. Hash and HashAlg will provide the hash value of the data along with Hash algorithm used to generate the hash.
// For RemoteAttachment, the uri will be a remote HTTP URL. Hash and HashAlg will provide the hash value of the data along with Hash algorithm used to generate the hash. Consumer of this API need to validate the hash value against the hash of the data object retrieved from the remote url
// For AttachmentEvidence, the uri will be empty. But the hash and hashAlg will provide the hash value of the data along with Hash algorithm used to generate the hash. Consumer of this API need to validate the hash value against the hash of the data object retrieved from the out of band.
func (c *Attachment) Type() string {
return c.attachment.Type[0]
}

// MimeType returns mime-type of the credential attachment.
func (c *Attachment) MimeType() string {
return c.attachment.MimeType
}

// Description returns the description of the credential attachment.
func (c *Attachment) Description() string {
return c.attachment.Description
}

// URI returns URI of the attachment. This could be embedded data or a link to external data.
func (c *Attachment) URI() string {
return c.attachment.URI
}

// Hash returns the hash of the attachment data.
func (c *Attachment) Hash() string {
return c.attachment.Hash
}

// HashAlg returns the hash algorithm used to hash the attachment data.
func (c *Attachment) HashAlg() string {
return c.attachment.HashAlg
}
5 changes: 3 additions & 2 deletions cmd/wallet-sdk-gomobile/docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -1199,7 +1199,7 @@ The structure of the display data object is as follows:

* Describes display information for a specific claim within a credential.
* Has `label()`, `rawID()`, `valueType()`, `value()`, `rawValue()`, `isMasked()`, `hasOrder()`, `order()`,
`pattern()`, and `locale()` methods.
`pattern()`, `attachment()` and `locale()` methods.
* For example, if the UI were to display "Given Name: Alice", then `label()` would correspond to "Given Name" while
`value()` would correspond to "Alice".
* Display order data is optional and will only exist if the issuer provided it. Use the `hasOrder()` method
Expand All @@ -1214,7 +1214,8 @@ The structure of the display data object is as follows:
* `rawID()` returns the claim's ID, which is the raw field name (key) from the VC associated with this claim.
It's not localized or formatted for display.
* `valueType()` returns the value type for this claim - when it's "image", then you should expect the value data to be
formatted using the [data URL scheme](https://www.rfc-editor.org/rfc/rfc2397).
formatted using the [data URL scheme](https://www.rfc-editor.org/rfc/rfc2397). For type=attachment, ignore the RawValue() and Value(), instead use Attachment() method.
* `attachment()` returns the attachment object for this claim. If the claim is not of type attachment. The object has `id()`, `type()`, `mimeType()`, `description()`, `URI()`, `hash()` and `hashAlg()` methods.

### Code Examples

Expand Down
39 changes: 30 additions & 9 deletions pkg/credentialschema/credentialdisplay.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
package credentialschema

import (
"encoding/json"
"errors"
"fmt"
"regexp"
Expand Down Expand Up @@ -213,6 +214,25 @@ func resolveClaim(
return nil, errClaimValueNotFoundInVC
}

var attachment *Attachment

if claim.ValueType == "attachment" {
switch untypedValue.(type) {
case map[string]interface{}:
attachmentJSON, err := json.Marshal(untypedValue)
if err != nil {
fmt.Println("json marshal attachment ", err)
}

attachment = &Attachment{}
if err := json.Unmarshal(attachmentJSON, &attachment); err != nil {
fmt.Println("json unmarshal attachment ", err)
}
default:
return nil, fmt.Errorf("unsupported attachment value '%v'", untypedValue)
}
}

rawValue := fmt.Sprintf("%v", untypedValue)

var value *string
Expand All @@ -234,15 +254,16 @@ func resolveClaim(
}

return &ResolvedClaim{
RawID: fieldName,
Label: label,
ValueType: claim.ValueType,
Order: order,
RawValue: rawValue,
Value: value,
Pattern: claim.Pattern,
Mask: claim.Mask,
Locale: labelLocale,
RawID: fieldName,
Label: label,
ValueType: claim.ValueType,
Order: order,
RawValue: rawValue,
Value: value,
Pattern: claim.Pattern,
Mask: claim.Mask,
Locale: labelLocale,
Attachment: attachment,
}, nil
}

Expand Down
30 changes: 21 additions & 9 deletions pkg/credentialschema/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,31 @@ type CredentialOverview struct {
type ResolvedClaim struct {
// RawID is the raw field name (key) from the VC associated with this claim.
// It's not localized or formatted for display.
RawID string `json:"raw_id,omitempty"`
Label string `json:"label,omitempty"`
ValueType string `json:"value_type,omitempty"`
RawValue string `json:"raw_value,omitempty"`
Value *string `json:"value,omitempty"`
Order *int `json:"order,omitempty"`
Pattern string `json:"pattern,omitempty"`
Mask string `json:"mask,omitempty"`
Locale string `json:"locale,omitempty"`
RawID string `json:"raw_id,omitempty"`
Label string `json:"label,omitempty"`
ValueType string `json:"value_type,omitempty"`
RawValue string `json:"raw_value,omitempty"`
Value *string `json:"value,omitempty"`
Order *int `json:"order,omitempty"`
Pattern string `json:"pattern,omitempty"`
Mask string `json:"mask,omitempty"`
Locale string `json:"locale,omitempty"`
Attachment *Attachment `json:"attachment,omitempty"`
}

// Logo represents display information for a logo.
type Logo struct {
URL string `json:"uri,omitempty"`
AltText string `json:"alt_text,omitempty"`
}

// Attachment contains data for display for a vc attachment.
type Attachment struct {
ID string `json:"id,omitempty"`
Type []string `json:"type,omitempty"`
MimeType string `json:"mimeType,omitempty"`
Description string `json:"description,omitempty"`
URI string `json:"uri,omitempty"`
Hash string `json:"hash,omitempty"`
HashAlg string `json:"hash-alg,omitempty"`
}

0 comments on commit 9333100

Please sign in to comment.