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 lk sync.Mutex
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 lk: sync.Mutex{},
34 }
35}
36
37func (p *Passport) FetchDoc(ctx context.Context, did string) (*DidDoc, error) {
38 skipCache, _ := ctx.Value("skip-cache").(bool)
39
40 if !skipCache {
41 cached, ok := p.bc.GetDoc(did)
42 if ok {
43 return cached, nil
44 }
45 }
46
47 p.lk.Lock() // this is pretty pathetic, and i should rethink this. but for now, fuck it
48 defer p.lk.Unlock()
49
50 doc, err := FetchDidDoc(ctx, p.h, did)
51 if err != nil {
52 return nil, err
53 }
54
55 p.bc.PutDoc(did, doc)
56
57 return doc, nil
58}
59
60func (p *Passport) ResolveHandle(ctx context.Context, handle string) (string, error) {
61 skipCache, _ := ctx.Value("skip-cache").(bool)
62
63 if !skipCache {
64 cached, ok := p.bc.GetDid(handle)
65 if ok {
66 return cached, nil
67 }
68 }
69
70 did, err := ResolveHandle(ctx, p.h, handle)
71 if err != nil {
72 return "", err
73 }
74
75 p.bc.PutDid(handle, did)
76
77 return did, nil
78}
79
80func (p *Passport) BustDoc(ctx context.Context, did string) error {
81 return p.bc.BustDoc(did)
82}
83
84func (p *Passport) BustDid(ctx context.Context, handle string) error {
85 return p.bc.BustDid(handle)
86}