Skip to content

Commit 23585f6

Browse files
authored
Filter for did document (#105)
did document verification methods filter
1 parent 4d32189 commit 23585f6

File tree

5 files changed

+576
-72
lines changed

5 files changed

+576
-72
lines changed

.github/workflows/ci-lint.yaml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,8 @@ jobs:
1212
- uses: actions/checkout@v4
1313
- uses: actions/setup-go@v5
1414
with:
15-
go-version: 1.23.4
16-
- name: install golangci-lint
17-
run:
18-
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $GITHUB_WORKSPACE v1.60.3
19-
- name: lint
20-
run: |
21-
go version
22-
$GITHUB_WORKSPACE/golangci-lint version
23-
$GITHUB_WORKSPACE/golangci-lint --config .golangci.yml run
15+
go-version: 1.24
16+
- name: golangci-lint
17+
uses: golangci/golangci-lint-action@v8
18+
with:
19+
version: v2.1

.github/workflows/ci-test.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ jobs:
2020
container: golang:${{ matrix.containers }}
2121
steps:
2222
- name: Checkout code
23-
uses: actions/checkout@v3
24-
- uses: actions/cache@v3
23+
uses: actions/checkout@v5
24+
- uses: actions/cache@v4
2525
with:
2626
path: |
2727
~/.cache/go-build

.golangci.yml

Lines changed: 45 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,57 @@
1-
service:
2-
golangci-lint-version: 1.60.3
3-
4-
run:
5-
timeout: 2m
6-
7-
linters-settings:
8-
govet:
9-
shadow: true
10-
maligned:
11-
suggest-new: true
12-
goconst:
13-
min-len: 2
14-
min-occurrences: 2
15-
misspell:
16-
locale: US
17-
lll:
18-
line-length: 140
19-
revive:
20-
min-confidence: 0.1
21-
rules:
22-
# Add more comments for exported functions and remove this rule
23-
- name: package-comments
24-
disabled: true
1+
version: "2"
252

263
linters:
274
enable:
285
- bodyclose
29-
- revive
30-
- govet
31-
- unconvert
6+
- copyloopvar
7+
- gochecknoinits
328
- gocyclo
339
- misspell
34-
- unparam
35-
- typecheck
36-
- ineffassign
37-
- stylecheck
38-
- gochecknoinits
39-
- copyloopvar
4010
- nakedret
41-
- gosimple
4211
- prealloc
43-
- goimports
44-
- gofmt
45-
- errcheck
12+
# - revive
4613
- staticcheck
47-
48-
## format - fill free to fix
49-
# - errcheck
50-
# - gofmt
51-
fast: false
14+
- unconvert
15+
- unparam
16+
- govet
17+
- ineffassign
18+
- errcheck
5219
disable:
5320
- dupl
21+
- revive # Fix comments later and re-enable
22+
settings:
23+
goconst:
24+
min-len: 2
25+
min-occurrences: 2
26+
lll:
27+
line-length: 140
28+
misspell:
29+
locale: US
30+
staticcheck:
31+
checks: ["all", "-QF1008"]
32+
exclusions:
33+
generated: lax
34+
rules:
35+
- linters:
36+
- staticcheck
37+
text: at least one file in a package should have a package comment
38+
- linters:
39+
- govet
40+
text: 'shadow: declaration of "err" shadows declaration'
41+
- linters:
42+
- dupl
43+
- gosec
44+
path: _test\.go
5445

55-
issues:
56-
exclude-rules:
57-
# - Fix and remove
58-
- text: "at least one file in a package should have a package comment"
59-
linters:
60-
- stylecheck
61-
# - Fix and remove
62-
- text: "package-comments: should have a package comment"
63-
linters:
64-
- revive
65-
- text: "shadow: declaration of \"err\" shadows declaration"
66-
linters:
67-
- govet
68-
- path: _test\.go
69-
linters:
70-
- gosec
71-
- dupl
72-
exclude-use-default: false
46+
formatters:
47+
enable:
48+
- gofmt
49+
- goimports
50+
- gci
51+
exclusions:
52+
generated: lax
53+
paths:
54+
- third_party$
55+
- builtin$
56+
- examples$
57+

verifiable/did_doc.go

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ package verifiable
22

33
import (
44
"encoding/json"
5+
liberr "errors"
56
"fmt"
67

78
"github.com/iden3/go-merkletree-sql/v2"
89
"github.com/pkg/errors"
910
)
1011

12+
var (
13+
ErrVerificationMethodNotFound = liberr.New("verification method not found")
14+
)
15+
1116
// DIDDocument defines current supported did doc model.
1217
type DIDDocument struct {
1318
Context interface{} `json:"@context"`
@@ -16,7 +21,78 @@ type DIDDocument struct {
1621
VerificationMethod []CommonVerificationMethod `json:"verificationMethod,omitempty"`
1722
AssertionMethod []Authentication `json:"assertionMethod,omitempty"`
1823
Authentication []Authentication `json:"authentication,omitempty"`
19-
KeyAgreement []interface{} `json:"keyAgreement,omitempty"`
24+
KeyAgreement []Authentication `json:"keyAgreement,omitempty"`
25+
}
26+
27+
func (d *DIDDocument) ResolveVerificationMethods() CommonVerificationMethods {
28+
return CommonVerificationMethods(d.VerificationMethod)
29+
}
30+
31+
func (d *DIDDocument) resolveToVM(items []Authentication) (CommonVerificationMethods, error) {
32+
vms := make(CommonVerificationMethods, 0, len(items))
33+
for _, auth := range items {
34+
if auth.IsDID() {
35+
vm, err := d.ResolveVerificationMethods().FilterBy(WithID(auth.DID()))
36+
if err != nil {
37+
return nil, err
38+
}
39+
if len(vm) != 1 {
40+
return nil,
41+
fmt.Errorf("found %d verification methods for did: %s", len(vm), auth.DID())
42+
}
43+
vms = append(vms, vm[0])
44+
continue
45+
}
46+
vms = append(vms, auth.CommonVerificationMethod)
47+
}
48+
return vms, nil
49+
}
50+
51+
func (d *DIDDocument) ResolveAssertionVerificationMethods() (CommonVerificationMethods, error) {
52+
return d.resolveToVM(d.AssertionMethod)
53+
}
54+
55+
func (d *DIDDocument) ResolveAuthVerificationMethods() (CommonVerificationMethods, error) {
56+
return d.resolveToVM(d.Authentication)
57+
}
58+
59+
func (d *DIDDocument) ResolveKeyAgreementVerificationMethods() (CommonVerificationMethods, error) {
60+
return d.resolveToVM(d.KeyAgreement)
61+
}
62+
63+
func (d *DIDDocument) AllVerificationMethods() CommonVerificationMethods {
64+
alllen := len(d.VerificationMethod) + len(d.Authentication) +
65+
len(d.AssertionMethod) + len(d.KeyAgreement)
66+
all := make(map[string]CommonVerificationMethod, alllen)
67+
68+
for _, vm := range d.VerificationMethod {
69+
all[vm.ID] = vm
70+
}
71+
72+
appendVMs := func(auths []Authentication) {
73+
for _, auth := range auths {
74+
if auth.IsDID() {
75+
continue
76+
}
77+
78+
if _, ok := all[auth.ID]; ok {
79+
continue
80+
}
81+
82+
all[auth.ID] = auth.CommonVerificationMethod
83+
}
84+
}
85+
86+
appendVMs(d.Authentication)
87+
appendVMs(d.AssertionMethod)
88+
appendVMs(d.KeyAgreement)
89+
90+
vms := make(CommonVerificationMethods, 0, len(all))
91+
for _, vm := range all {
92+
vms = append(vms, vm)
93+
}
94+
95+
return vms
2096
}
2197

2298
// Service describes standard DID document service field.
@@ -55,6 +131,8 @@ type DeviceMetadata struct {
55131
PushToken string `json:"push_token"`
56132
}
57133

134+
type CommonVerificationMethods []CommonVerificationMethod
135+
58136
// CommonVerificationMethod DID doc verification method.
59137
type CommonVerificationMethod struct {
60138
ID string `json:"id"`
@@ -182,3 +260,77 @@ type IdentityState struct {
182260
Info *StateInfo `json:"info,omitempty"`
183261
Global *GistInfo `json:"global,omitempty"`
184262
}
263+
264+
type VerificationMethodFilter struct {
265+
byID string
266+
byType string
267+
byController string
268+
byJWKType string
269+
byJWKAlgorithm string
270+
}
271+
272+
type VerificationMethodFilterOpt func(*VerificationMethodFilter)
273+
274+
func WithID(id string) VerificationMethodFilterOpt {
275+
return func(f *VerificationMethodFilter) {
276+
f.byID = id
277+
}
278+
}
279+
280+
func WithType(typ string) VerificationMethodFilterOpt {
281+
return func(f *VerificationMethodFilter) {
282+
f.byType = typ
283+
}
284+
}
285+
286+
func WithController(controller string) VerificationMethodFilterOpt {
287+
return func(f *VerificationMethodFilter) {
288+
f.byController = controller
289+
}
290+
}
291+
292+
func WithJWKType(keyType string) VerificationMethodFilterOpt {
293+
return func(f *VerificationMethodFilter) {
294+
f.byJWKType = keyType
295+
}
296+
}
297+
298+
func WithJWKAlgorithm(algorithm string) VerificationMethodFilterOpt {
299+
return func(f *VerificationMethodFilter) {
300+
f.byJWKAlgorithm = algorithm
301+
}
302+
}
303+
304+
func (cvm CommonVerificationMethods) FilterBy(opts ...VerificationMethodFilterOpt) (CommonVerificationMethods, error) {
305+
if len(opts) == 0 {
306+
return nil, fmt.Errorf("empty filter options")
307+
}
308+
var filter VerificationMethodFilter
309+
for _, opt := range opts {
310+
opt(&filter)
311+
}
312+
313+
filtered := CommonVerificationMethods{}
314+
for _, vm := range cvm {
315+
if filter.byID != "" && vm.ID != filter.byID {
316+
continue
317+
}
318+
if filter.byType != "" && vm.Type != filter.byType {
319+
continue
320+
}
321+
if filter.byController != "" && vm.Controller != filter.byController {
322+
continue
323+
}
324+
if filter.byJWKType != "" && vm.PublicKeyJwk["kty"] != filter.byJWKType {
325+
continue
326+
}
327+
if filter.byJWKAlgorithm != "" && vm.PublicKeyJwk["alg"] != filter.byJWKAlgorithm {
328+
continue
329+
}
330+
filtered = append(filtered, vm)
331+
}
332+
if filter.byID != "" && len(filtered) > 1 {
333+
return filtered[:1], nil
334+
}
335+
return filtered, nil
336+
}

0 commit comments

Comments
 (0)