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

Commit

Permalink
Merge branch 'main' into feature/add_sqlite_mobile_impl
Browse files Browse the repository at this point in the history
  • Loading branch information
sudeshrshetty authored Aug 9, 2022
2 parents ca7c46d + 1daefcc commit 402bdce
Show file tree
Hide file tree
Showing 8 changed files with 1,053 additions and 31 deletions.
8 changes: 4 additions & 4 deletions pkg/doc/cm/credentialmanifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ type LabeledDisplayMappingObject struct {
// Schema represents Type and (optional) Format information for a DisplayMappingObject that uses the Paths field,
// as defined in https://identity.foundation/credential-manifest/wallet-rendering/#using-path.
type Schema struct {
Type string `json:"type,omitempty"` // MUST be here
Format string `json:"format,omitempty"` // MAY be here if the Type is "string".
ContentMediaType string `json:"mediatype,omitempty"` // MAY be here if the Type is "string".
ContentEncoding string `json:"encoding,omitempty"` // MAY be here if the Type is "string".
Type string `json:"type,omitempty"` // MUST be here
Format string `json:"format,omitempty"` // MAY be here if the Type is "string".
ContentMediaType string `json:"contentMediaType,omitempty"` // MAY be here if the Type is "string".
ContentEncoding string `json:"contentEncoding,omitempty"` // MAY be here if the Type is "string".
}

type staticDisplayMappingObjects struct {
Expand Down
130 changes: 111 additions & 19 deletions pkg/doc/presexch/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
)

const (

// All rule`s value.
All Selection = "all"
// Pick rule`s value.
Expand All @@ -38,6 +39,8 @@ const (
Preferred Preference = "preferred"

tmpEnding = "tmp_unique_id_"

credentialSchema = "credentialSchema"
)

var errPathNotApplicable = errors.New("path not applicable")
Expand Down Expand Up @@ -93,6 +96,8 @@ type PresentationDefinition struct {
// Format is an object with one or more properties matching the registered Claim Format Designations
// (jwt, jwt_vc, jwt_vp, etc.) to inform the Holder of the claim format configurations the Verifier can process.
Format *Format `json:"format,omitempty"`
// Frame is used for JSON-LD document framing.
Frame map[string]interface{} `json:"frame,omitempty"`
// SubmissionRequirements must conform to the Submission Requirement Format.
// If not present, all inputs listed in the InputDescriptors array are required for submission.
SubmissionRequirements []*SubmissionRequirement `json:"submission_requirements,omitempty"`
Expand Down Expand Up @@ -121,6 +126,7 @@ type InputDescriptor struct {
Metadata map[string]interface{} `json:"metadata,omitempty"`
Schema []*Schema `json:"schema,omitempty"`
Constraints *Constraints `json:"constraints,omitempty"`
Format *Format `json:"format,omitempty"`
}

// Schema input descriptor schema.
Expand All @@ -145,11 +151,12 @@ type Constraints struct {

// Field describes Constraints`s Fields field.
type Field struct {
Path []string `json:"path,omitempty"`
ID string `json:"id,omitempty"`
Purpose string `json:"purpose,omitempty"`
Filter *Filter `json:"filter,omitempty"`
Predicate *Preference `json:"predicate,omitempty"`
Path []string `json:"path,omitempty"`
ID string `json:"id,omitempty"`
Purpose string `json:"purpose,omitempty"`
Filter *Filter `json:"filter,omitempty"`
Predicate *Preference `json:"predicate,omitempty"`
IntentToRetain bool `json:"intent_to_retain,omitempty"`
}

// Filter describes filter.
Expand All @@ -171,11 +178,21 @@ type Filter struct {
// ValidateSchema validates presentation definition.
func (pd *PresentationDefinition) ValidateSchema() error {
result, err := gojsonschema.Validate(
gojsonschema.NewStringLoader(DefinitionJSONSchema),
gojsonschema.NewStringLoader(DefinitionJSONSchemaV1),
gojsonschema.NewGoLoader(struct {
PD *PresentationDefinition `json:"presentation_definition"`
}{PD: pd}),
)

if err != nil || !result.Valid() {
result, err = gojsonschema.Validate(
gojsonschema.NewStringLoader(DefinitionJSONSchemaV2),
gojsonschema.NewGoLoader(struct {
PD *PresentationDefinition `json:"presentation_definition"`
}{PD: pd}),
)
}

if err != nil {
return err
}
Expand Down Expand Up @@ -310,7 +327,7 @@ func (pd *PresentationDefinition) CreateVP(credentials []*verifiable.Credential,
return nil, err
}

result, err := applyRequirement(req, credentials, documentLoader, opts...)
result, err := pd.applyRequirement(req, credentials, documentLoader, opts...)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -340,14 +357,33 @@ func (pd *PresentationDefinition) CreateVP(credentials []*verifiable.Credential,
var ErrNoCredentials = errors.New("credentials do not satisfy requirements")

// nolint: gocyclo,funlen,gocognit
func applyRequirement(req *requirement, creds []*verifiable.Credential,
func (pd *PresentationDefinition) applyRequirement(req *requirement, creds []*verifiable.Credential,
documentLoader ld.DocumentLoader, opts ...verifiable.CredentialOpt) (map[string][]*verifiable.Credential, error) {
result := make(map[string][]*verifiable.Credential)

for _, descriptor := range req.InputDescriptors {
filtered := filterSchema(descriptor.Schema, creds, documentLoader)
format := pd.Format
if descriptor.Format != nil {
format = descriptor.Format
}

filtered := creds

filtered, err := frameCreds(pd.Frame, filtered, opts...)
if err != nil {
return nil, err
}

if format != nil {
filtered = filterFormat(format, filtered)
}

// Validate schema only for v1
if descriptor.Schema != nil {
filtered = filterSchema(descriptor.Schema, filtered, documentLoader)
}

filtered, err := filterConstraints(descriptor.Constraints, filtered, opts...)
filtered, err = filterConstraints(descriptor.Constraints, filtered, opts...)
if err != nil {
return nil, err
}
Expand All @@ -371,7 +407,7 @@ func applyRequirement(req *requirement, creds []*verifiable.Credential,
set := map[string]map[string]string{}

for _, r := range req.Nested {
res, err := applyRequirement(r, creds, documentLoader, opts...)
res, err := pd.applyRequirement(r, creds, documentLoader, opts...)
if errors.Is(err, ErrNoCredentials) {
continue
}
Expand Down Expand Up @@ -594,10 +630,30 @@ func filterConstraints(constraints *Constraints, creds []*verifiable.Credential,
return result, nil
}

func frameCreds(frame map[string]interface{}, creds []*verifiable.Credential,
opts ...verifiable.CredentialOpt) ([]*verifiable.Credential, error) {
if frame == nil {
return creds, nil
}

var result []*verifiable.Credential

for _, credential := range creds {
bbsVC, err := credential.GenerateBBSSelectiveDisclosure(frame, nil, opts...)
if err != nil {
return nil, err
}

result = append(result, bbsVC)
}

return result, nil
}

func toSubject(subject interface{}) interface{} {
sub, ok := subject.([]verifiable.Subject)
if ok && len(sub) == 1 {
return sub[0]
return verifiable.Subject{ID: sub[0].ID}
}

return subject
Expand Down Expand Up @@ -650,6 +706,10 @@ func createNewCredential(constraints *Constraints, src, limitedCred []byte,
}

for _, path := range jPaths {
if strings.Contains(path[0], credentialSchema) {
continue
}

var val interface{} = true

if !modifiedByPredicate {
Expand Down Expand Up @@ -772,26 +832,40 @@ func hasBBS(vc *verifiable.Credential) bool {
return false
}

func hasProofWithType(vc *verifiable.Credential, proofType string) bool {
for _, proof := range vc.Proofs {
if proof["type"] == proofType {
return true
}
}

return false
}

func filterField(f *Field, credential map[string]interface{}) error {
var schema gojsonschema.JSONLoader

if f.Filter != nil {
schema = gojsonschema.NewGoLoader(*f.Filter)
}

var lastErr error

for _, path := range f.Path {
patch, err := jsonpath.Get(path, credential)
if err != nil {
return errPathNotApplicable
}
if err == nil {
err = validatePatch(schema, patch)
if err == nil {
return nil
}

err = validatePatch(schema, patch)
if err != nil {
return err
lastErr = err
} else {
lastErr = errPathNotApplicable
}
}

return nil
return lastErr
}

func validatePatch(schema gojsonschema.JSONLoader, patch interface{}) error {
Expand Down Expand Up @@ -888,6 +962,24 @@ func (a byID) Len() int { return len(a) }
func (a byID) Less(i, j int) bool { return a[i].ID < a[j].ID }
func (a byID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

func filterFormat(format *Format, credentials []*verifiable.Credential) []*verifiable.Credential {
var result []*verifiable.Credential

if format.LdpVP == nil {
return result
}

for _, credential := range credentials {
for _, proofType := range format.LdpVP.ProofType {
if hasProofWithType(credential, proofType) {
result = append(result, credential)
}
}
}

return result
}

// nolint: gocyclo
func filterSchema(schemas []*Schema, credentials []*verifiable.Credential,
documentLoader ld.DocumentLoader) []*verifiable.Credential {
Expand Down
8 changes: 6 additions & 2 deletions pkg/doc/presexch/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,9 @@ func TestPresentationDefinition_CreateVP(t *testing.T) {
Constraints: &Constraints{
SubjectIsIssuer: &subIsIssuerRequired,
Fields: []*Field{{
Path: []string{"$.first_name", "$.last_name"},
Path: []string{"$.first_name"},
}, {
Path: []string{"$.last_name"},
}},
},
}, {
Expand All @@ -1042,7 +1044,9 @@ func TestPresentationDefinition_CreateVP(t *testing.T) {
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.first_name", "$.last_name"},
Path: []string{"$.first_name"},
}, {
Path: []string{"$.last_name"},
}},
},
}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (

const dummy = "DUMMY"

func ExamplePresentationDefinition_CreateVP() {
func ExamplePresentationDefinition_CreateVP_v1() {
required := Required

pd := &PresentationDefinition{
Expand Down
Loading

0 comments on commit 402bdce

Please sign in to comment.