An atproto PDS written in Go
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}