1package identity
2
3import (
4 "context"
5 "net/http"
6 "sync"
7)
8
9type BackingCache interface {
10 GetDoc(did string) (*DidDoc, bool)
11 PutDoc(did string, doc *DidDoc) error
12 BustDoc(did string) error
13
14 GetDid(handle string) (string, bool)
15 PutDid(handle string, did string) error
16 BustDid(handle string) error
17}
18
19type Passport struct {
20 h *http.Client
21 bc BackingCache
22 mu sync.RWMutex
23}
24
25func NewPassport(h *http.Client, bc BackingCache) *Passport {
26 if h == nil {
27 h = http.DefaultClient
28 }
29
30 return &Passport{
31 h: h,
32 bc: bc,
33 }
34}
35
36func (p *Passport) FetchDoc(ctx context.Context, did string) (*DidDoc, error) {
37 skipCache, _ := ctx.Value("skip-cache").(bool)
38
39 if !skipCache {
40 p.mu.RLock()
41 cached, ok := p.bc.GetDoc(did)
42 p.mu.RUnlock()
43
44 if ok {
45 return cached, nil
46 }
47 }
48
49 doc, err := FetchDidDoc(ctx, p.h, did)
50 if err != nil {
51 return nil, err
52 }
53
54 p.mu.Lock()
55 p.bc.PutDoc(did, doc)
56 p.mu.Unlock()
57
58 return doc, nil
59}
60
61func (p *Passport) ResolveHandle(ctx context.Context, handle string) (string, error) {
62 skipCache, _ := ctx.Value("skip-cache").(bool)
63
64 if !skipCache {
65 p.mu.RLock()
66 cached, ok := p.bc.GetDid(handle)
67 p.mu.RUnlock()
68
69 if ok {
70 return cached, nil
71 }
72 }
73
74 did, err := ResolveHandle(ctx, p.h, handle)
75 if err != nil {
76 return "", err
77 }
78
79 p.mu.Lock()
80 p.bc.PutDid(handle, did)
81 p.mu.Unlock()
82
83 return did, nil
84}
85
86func (p *Passport) BustDoc(ctx context.Context, did string) error {
87 p.mu.Lock()
88 defer p.mu.Unlock()
89 return p.bc.BustDoc(did)
90}
91
92func (p *Passport) BustDid(ctx context.Context, handle string) error {
93 p.mu.Lock()
94 defer p.mu.Unlock()
95 return p.bc.BustDid(handle)
96}