/
model.go
157 lines (136 loc) · 5.65 KB
/
model.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package manifest
import (
"reflect"
"github.com/TBD54566975/ssi-sdk/credential/exchange"
"github.com/TBD54566975/ssi-sdk/credential/rendering"
"github.com/TBD54566975/ssi-sdk/util"
"github.com/pkg/errors"
)
const (
CredentialManifestJSONProperty = "credential_manifest"
CredentialApplicationJSONProperty = "credential_application"
CredentialResponseJSONProperty = "credential_response"
)
// CredentialManifest https://identity.foundation/credential-manifest/#general-composition
type CredentialManifest struct {
ID string `json:"id" validate:"required"`
SpecVersion string `json:"spec_version" validate:"required"`
Issuer Issuer `json:"issuer" validate:"required,dive"`
OutputDescriptors []OutputDescriptor `json:"output_descriptors" validate:"required,dive"`
Format *exchange.ClaimFormat `json:"format,omitempty" validate:"omitempty,dive"`
PresentationDefinition *exchange.PresentationDefinition `json:"presentation_definition,omitempty" validate:"omitempty,dive"`
}
func (cm *CredentialManifest) IsEmpty() bool {
if cm == nil {
return true
}
return reflect.DeepEqual(cm, &CredentialManifest{})
}
func (cm *CredentialManifest) IsValid() error {
if cm.IsEmpty() {
return errors.New("manifest is empty")
}
// validate against json schema
if err := IsValidCredentialManifest(*cm); err != nil {
return errors.Wrap(err, "manifest failed json schema validation")
}
// validate against json schema
if err := AreValidOutputDescriptors(cm.OutputDescriptors); err != nil {
return errors.Wrap(err, "manifest's output descriptors failed json schema validation")
}
// validate against struct tags
return util.NewValidator().Struct(cm)
}
type Issuer struct {
ID string `json:"id" validate:"required"`
Name string `json:"name,omitempty"`
// an object or URI as defined by the DIF Entity Styles specification
// https://identity.foundation/wallet-rendering/#entity-styles
Styles *rendering.EntityStyleDescriptor `json:"styles,omitempty"`
}
// OutputDescriptor https://identity.foundation/credential-manifest/#output-descriptor
type OutputDescriptor struct {
// Must be unique within a manifest
ID string `json:"id" validate:"required"`
Schema string `json:"schema" validate:"required"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
// both below: an object or URI as defined by the DIF Entity Styles specification
Display *rendering.DataDisplay `json:"display,omitempty"`
Styles *rendering.EntityStyleDescriptor `json:"styles,omitempty"`
}
func (od *OutputDescriptor) IsEmpty() bool {
if od == nil {
return true
}
return reflect.DeepEqual(od, &OutputDescriptor{})
}
func (od *OutputDescriptor) IsValid() error {
return util.NewValidator().Struct(od)
}
type CredentialApplicationWrapper struct {
CredentialApplication CredentialApplication `json:"credential_application"`
Credentials []interface{} `json:"verifiableCredentials,omitempty"`
}
// CredentialApplication https://identity.foundation/credential-manifest/#credential-application
type CredentialApplication struct {
ID string `json:"id" validate:"required"`
SpecVersion string `json:"spec_version" validate:"required"`
ManifestID string `json:"manifest_id" validate:"required"`
Format *exchange.ClaimFormat `json:"format" validate:"required,dive"`
// Must be present if the corresponding manifest contains a presentation_definition
PresentationSubmission *exchange.PresentationSubmission `json:"presentation_submission,omitempty" validate:"omitempty,dive"`
}
func (ca *CredentialApplication) IsEmpty() bool {
if ca == nil {
return true
}
return reflect.DeepEqual(ca, &CredentialApplication{})
}
func (ca *CredentialApplication) IsValid() error {
if ca.IsEmpty() {
return errors.New("application is empty")
}
if err := IsValidCredentialApplication(*ca); err != nil {
return errors.Wrap(err, "application failed json schema validation")
}
if ca.Format != nil {
if err := exchange.IsValidDefinitionClaimFormatDesignation(*ca.Format); err != nil {
return errors.Wrap(err, "application's claim format failed json schema validation")
}
}
return util.NewValidator().Struct(ca)
}
type CredentialResponseWrapper struct {
CredentialResponse CredentialResponse `json:"credential_response"`
Credentials []interface{} `json:"verifiableCredentials,omitempty"`
}
// CredentialResponse https://identity.foundation/credential-manifest/#credential-response
type CredentialResponse struct {
ID string `json:"id" validate:"required"`
SpecVersion string `json:"spec_version" validate:"required"`
ManifestID string `json:"manifest_id" validate:"required"`
ApplicationID string `json:"application_id"`
Fulfillment *struct {
DescriptorMap []exchange.SubmissionDescriptor `json:"descriptor_map" validate:"required"`
} `json:"fulfillment,omitempty" validate:"omitempty,dive"`
Denial *struct {
Reason string `json:"reason" validate:"required"`
InputDescriptors []string `json:"input_descriptors,omitempty"`
} `json:"denial,omitempty" validate:"omitempty,dive"`
}
func (cf *CredentialResponse) IsEmpty() bool {
if cf == nil {
return true
}
return reflect.DeepEqual(cf, &CredentialResponse{})
}
func (cf *CredentialResponse) IsValid() error {
if cf.IsEmpty() {
return errors.New("response is empty")
}
if err := IsValidCredentialResponse(*cf); err != nil {
return errors.Wrap(err, "response failed json schema validation")
}
return util.NewValidator().Struct(cf)
}