this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

identity: rename Catalog to Directory

+305 -305
+13 -13
atproto/identity/basic_catalog.go atproto/identity/base_directory.go
··· 7 7 "github.com/bluesky-social/indigo/atproto/syntax" 8 8 ) 9 9 10 - type BasicCatalog struct { 10 + type BasicDirectory struct { 11 11 PLCURL string 12 12 } 13 13 14 - var _ Catalog = (*BasicCatalog)(nil) 14 + var _ Directory = (*BasicDirectory)(nil) 15 15 16 - func NewBasicCatalog(plcURL string) BasicCatalog { 16 + func NewBasicDirectory(plcURL string) BasicDirectory { 17 17 if plcURL == "" { 18 18 plcURL = DefaultPLCURL 19 19 } 20 - return BasicCatalog{ 20 + return BasicDirectory{ 21 21 PLCURL: plcURL, 22 22 } 23 23 } 24 24 25 - func (c *BasicCatalog) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error) { 25 + func (d *BasicDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error) { 26 26 switch did.Method() { 27 27 case "web": 28 28 return ResolveDIDWeb(ctx, did) 29 29 case "plc": 30 - return ResolveDIDPLC(ctx, c.PLCURL, did) 30 + return ResolveDIDPLC(ctx, d.PLCURL, did) 31 31 default: 32 32 return nil, fmt.Errorf("DID method not supported: %s", did.Method()) 33 33 } 34 34 } 35 35 36 - func (c *BasicCatalog) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) { 36 + func (d *BasicDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) { 37 37 did, err := ResolveHandle(ctx, h) 38 38 if err != nil { 39 39 return nil, err 40 40 } 41 - doc, err := c.ResolveDID(ctx, did) 41 + doc, err := d.ResolveDID(ctx, did) 42 42 if err != nil { 43 43 return nil, err 44 44 } ··· 60 60 return &ident, nil 61 61 } 62 62 63 - func (c *BasicCatalog) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) { 64 - doc, err := c.ResolveDID(ctx, did) 63 + func (d *BasicDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) { 64 + doc, err := d.ResolveDID(ctx, did) 65 65 if err != nil { 66 66 return nil, err 67 67 } ··· 86 86 return &ident, nil 87 87 } 88 88 89 - func (c *BasicCatalog) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) { 89 + func (d *BasicDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) { 90 90 handle, err := a.AsHandle() 91 91 if nil == err { // if *not* an error 92 - return c.LookupHandle(ctx, handle) 92 + return d.LookupHandle(ctx, handle) 93 93 } 94 94 did, err := a.AsDID() 95 95 if nil == err { // if *not* an error 96 - return c.LookupDID(ctx, did) 96 + return d.LookupDID(ctx, did) 97 97 } 98 98 return nil, fmt.Errorf("at-identifier neither a Handle nor a DID") 99 99 }
-205
atproto/identity/cache_catalog.go
··· 1 - package identity 2 - 3 - import ( 4 - "context" 5 - "fmt" 6 - "sync" 7 - "time" 8 - 9 - "github.com/bluesky-social/indigo/atproto/syntax" 10 - ) 11 - 12 - type CacheCatalog struct { 13 - HitTTL time.Duration 14 - ErrTTL time.Duration 15 - Inner Catalog 16 - mutex sync.RWMutex 17 - handleCache map[syntax.Handle]HandleEntry 18 - identityCache map[syntax.DID]IdentityEntry 19 - } 20 - 21 - type HandleEntry struct { 22 - Updated time.Time 23 - DID syntax.DID 24 - Err error 25 - } 26 - 27 - type IdentityEntry struct { 28 - Updated time.Time 29 - Identity *Identity 30 - Err error 31 - } 32 - 33 - var _ Catalog = (*CacheCatalog)(nil) 34 - 35 - func NewCacheCatalog(inner Catalog) CacheCatalog { 36 - // NOTE: these are kind of arbitrary default values... 37 - hitTTL := time.Duration(1e9 * 60 * 60) // 1 hour 38 - errTTL := time.Duration(1e9 * 60 * 2) // 2 minutes 39 - return CacheCatalog{ 40 - HitTTL: hitTTL, 41 - ErrTTL: errTTL, 42 - Inner: inner, 43 - handleCache: make(map[syntax.Handle]HandleEntry, 10), 44 - identityCache: make(map[syntax.DID]IdentityEntry, 10), 45 - } 46 - } 47 - 48 - func (c *CacheCatalog) IsHandleStale(e *HandleEntry) bool { 49 - if nil == e.Err && time.Since(e.Updated) > c.HitTTL { 50 - return true 51 - } 52 - if e.Err != nil && time.Since(e.Updated) > c.ErrTTL { 53 - return true 54 - } 55 - return false 56 - } 57 - 58 - func (c *CacheCatalog) IsIdentityStale(e *IdentityEntry) bool { 59 - if nil == e.Err && time.Since(e.Updated) > c.HitTTL { 60 - return true 61 - } 62 - if e.Err != nil && time.Since(e.Updated) > c.ErrTTL { 63 - return true 64 - } 65 - return false 66 - } 67 - 68 - func (c *CacheCatalog) updateHandle(ctx context.Context, h syntax.Handle) (*HandleEntry, error) { 69 - ident, err := c.Inner.LookupHandle(ctx, h) 70 - if err != nil { 71 - he := HandleEntry{ 72 - Updated: time.Now(), 73 - DID: "", 74 - Err: err, 75 - } 76 - c.mutex.Lock() 77 - c.handleCache[h] = he 78 - c.mutex.Unlock() 79 - return &he, nil 80 - } 81 - 82 - entry := IdentityEntry{ 83 - Updated: time.Now(), 84 - Identity: ident, 85 - Err: nil, 86 - } 87 - he := HandleEntry{ 88 - Updated: time.Now(), 89 - DID: ident.DID, 90 - Err: nil, 91 - } 92 - 93 - c.mutex.Lock() 94 - c.identityCache[ident.DID] = entry 95 - c.handleCache[ident.Handle] = he 96 - c.mutex.Unlock() 97 - return &he, nil 98 - } 99 - 100 - func (c *CacheCatalog) ResolveHandle(ctx context.Context, h syntax.Handle) (syntax.DID, error) { 101 - var err error 102 - var entry *HandleEntry 103 - c.mutex.RLock() 104 - maybeEntry, ok := c.handleCache[h] 105 - c.mutex.RUnlock() 106 - 107 - if !ok { 108 - entry, err = c.updateHandle(ctx, h) 109 - if err != nil { 110 - return "", err 111 - } 112 - } else { 113 - entry = &maybeEntry 114 - } 115 - if c.IsHandleStale(entry) { 116 - entry, err = c.updateHandle(ctx, h) 117 - if err != nil { 118 - return "", err 119 - } 120 - } 121 - return entry.DID, entry.Err 122 - } 123 - 124 - func (c *CacheCatalog) updateDID(ctx context.Context, did syntax.DID) (*IdentityEntry, error) { 125 - ident, err := c.Inner.LookupDID(ctx, did) 126 - // persist the identity lookup error, instead of processing it immediately 127 - entry := IdentityEntry{ 128 - Updated: time.Now(), 129 - Identity: ident, 130 - Err: err, 131 - } 132 - var he *HandleEntry 133 - // if *not* an error, then also update the handle cache 134 - if nil == err && !ident.Handle.IsInvalidHandle() { 135 - he = &HandleEntry{ 136 - Updated: time.Now(), 137 - DID: did, 138 - Err: nil, 139 - } 140 - } 141 - 142 - c.mutex.Lock() 143 - c.identityCache[did] = entry 144 - if he != nil { 145 - c.handleCache[ident.Handle] = *he 146 - } 147 - c.mutex.Unlock() 148 - return &entry, nil 149 - } 150 - 151 - func (c *CacheCatalog) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) { 152 - var err error 153 - var entry *IdentityEntry 154 - c.mutex.RLock() 155 - maybeEntry, ok := c.identityCache[did] 156 - c.mutex.RUnlock() 157 - 158 - if !ok { 159 - entry, err = c.updateDID(ctx, did) 160 - if err != nil { 161 - return nil, err 162 - } 163 - } else { 164 - entry = &maybeEntry 165 - } 166 - if c.IsIdentityStale(entry) { 167 - entry, err = c.updateDID(ctx, did) 168 - if err != nil { 169 - return nil, err 170 - } 171 - } 172 - return entry.Identity, entry.Err 173 - } 174 - 175 - func (c *CacheCatalog) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) { 176 - did, err := c.ResolveHandle(ctx, h) 177 - if err != nil { 178 - return nil, err 179 - } 180 - ident, err := c.LookupDID(ctx, did) 181 - if err != nil { 182 - return nil, err 183 - } 184 - 185 - declared, err := ident.DeclaredHandle() 186 - if err != nil { 187 - return nil, err 188 - } 189 - if declared != h { 190 - return nil, fmt.Errorf("handle does not match that declared in DID document") 191 - } 192 - return ident, nil 193 - } 194 - 195 - func (c *CacheCatalog) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) { 196 - handle, err := a.AsHandle() 197 - if nil == err { // if not an error, is a handle 198 - return c.LookupHandle(ctx, handle) 199 - } 200 - did, err := a.AsDID() 201 - if nil == err { // if not an error, is a DID 202 - return c.LookupDID(ctx, did) 203 - } 204 - return nil, fmt.Errorf("at-identifier neither a Handle nor a DID") 205 - }
+205
atproto/identity/cache_directory.go
··· 1 + package identity 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + "sync" 7 + "time" 8 + 9 + "github.com/bluesky-social/indigo/atproto/syntax" 10 + ) 11 + 12 + type CacheDirectory struct { 13 + HitTTL time.Duration 14 + ErrTTL time.Duration 15 + Inner Directory 16 + mutex sync.RWMutex 17 + handleCache map[syntax.Handle]HandleEntry 18 + identityCache map[syntax.DID]IdentityEntry 19 + } 20 + 21 + type HandleEntry struct { 22 + Updated time.Time 23 + DID syntax.DID 24 + Err error 25 + } 26 + 27 + type IdentityEntry struct { 28 + Updated time.Time 29 + Identity *Identity 30 + Err error 31 + } 32 + 33 + var _ Directory = (*CacheDirectory)(nil) 34 + 35 + func NewCacheDirectory(inner Directory) CacheDirectory { 36 + // NOTE: these are kind of arbitrary default values... 37 + hitTTL := time.Duration(1e9 * 60 * 60) // 1 hour 38 + errTTL := time.Duration(1e9 * 60 * 2) // 2 minutes 39 + return CacheDirectory{ 40 + HitTTL: hitTTL, 41 + ErrTTL: errTTL, 42 + Inner: inner, 43 + handleCache: make(map[syntax.Handle]HandleEntry, 10), 44 + identityCache: make(map[syntax.DID]IdentityEntry, 10), 45 + } 46 + } 47 + 48 + func (d *CacheDirectory) IsHandleStale(e *HandleEntry) bool { 49 + if nil == e.Err && time.Since(e.Updated) > d.HitTTL { 50 + return true 51 + } 52 + if e.Err != nil && time.Since(e.Updated) > d.ErrTTL { 53 + return true 54 + } 55 + return false 56 + } 57 + 58 + func (d *CacheDirectory) IsIdentityStale(e *IdentityEntry) bool { 59 + if nil == e.Err && time.Since(e.Updated) > d.HitTTL { 60 + return true 61 + } 62 + if e.Err != nil && time.Since(e.Updated) > d.ErrTTL { 63 + return true 64 + } 65 + return false 66 + } 67 + 68 + func (d *CacheDirectory) updateHandle(ctx context.Context, h syntax.Handle) (*HandleEntry, error) { 69 + ident, err := d.Inner.LookupHandle(ctx, h) 70 + if err != nil { 71 + he := HandleEntry{ 72 + Updated: time.Now(), 73 + DID: "", 74 + Err: err, 75 + } 76 + d.mutex.Lock() 77 + d.handleCache[h] = he 78 + d.mutex.Unlock() 79 + return &he, nil 80 + } 81 + 82 + entry := IdentityEntry{ 83 + Updated: time.Now(), 84 + Identity: ident, 85 + Err: nil, 86 + } 87 + he := HandleEntry{ 88 + Updated: time.Now(), 89 + DID: ident.DID, 90 + Err: nil, 91 + } 92 + 93 + d.mutex.Lock() 94 + d.identityCache[ident.DID] = entry 95 + d.handleCache[ident.Handle] = he 96 + d.mutex.Unlock() 97 + return &he, nil 98 + } 99 + 100 + func (d *CacheDirectory) ResolveHandle(ctx context.Context, h syntax.Handle) (syntax.DID, error) { 101 + var err error 102 + var entry *HandleEntry 103 + d.mutex.RLock() 104 + maybeEntry, ok := d.handleCache[h] 105 + d.mutex.RUnlock() 106 + 107 + if !ok { 108 + entry, err = d.updateHandle(ctx, h) 109 + if err != nil { 110 + return "", err 111 + } 112 + } else { 113 + entry = &maybeEntry 114 + } 115 + if d.IsHandleStale(entry) { 116 + entry, err = d.updateHandle(ctx, h) 117 + if err != nil { 118 + return "", err 119 + } 120 + } 121 + return entry.DID, entry.Err 122 + } 123 + 124 + func (d *CacheDirectory) updateDID(ctx context.Context, did syntax.DID) (*IdentityEntry, error) { 125 + ident, err := d.Inner.LookupDID(ctx, did) 126 + // persist the identity lookup error, instead of processing it immediately 127 + entry := IdentityEntry{ 128 + Updated: time.Now(), 129 + Identity: ident, 130 + Err: err, 131 + } 132 + var he *HandleEntry 133 + // if *not* an error, then also update the handle cache 134 + if nil == err && !ident.Handle.IsInvalidHandle() { 135 + he = &HandleEntry{ 136 + Updated: time.Now(), 137 + DID: did, 138 + Err: nil, 139 + } 140 + } 141 + 142 + d.mutex.Lock() 143 + d.identityCache[did] = entry 144 + if he != nil { 145 + d.handleCache[ident.Handle] = *he 146 + } 147 + d.mutex.Unlock() 148 + return &entry, nil 149 + } 150 + 151 + func (d *CacheDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) { 152 + var err error 153 + var entry *IdentityEntry 154 + d.mutex.RLock() 155 + maybeEntry, ok := d.identityCache[did] 156 + d.mutex.RUnlock() 157 + 158 + if !ok { 159 + entry, err = d.updateDID(ctx, did) 160 + if err != nil { 161 + return nil, err 162 + } 163 + } else { 164 + entry = &maybeEntry 165 + } 166 + if d.IsIdentityStale(entry) { 167 + entry, err = d.updateDID(ctx, did) 168 + if err != nil { 169 + return nil, err 170 + } 171 + } 172 + return entry.Identity, entry.Err 173 + } 174 + 175 + func (d *CacheDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) { 176 + did, err := d.ResolveHandle(ctx, h) 177 + if err != nil { 178 + return nil, err 179 + } 180 + ident, err := d.LookupDID(ctx, did) 181 + if err != nil { 182 + return nil, err 183 + } 184 + 185 + declared, err := ident.DeclaredHandle() 186 + if err != nil { 187 + return nil, err 188 + } 189 + if declared != h { 190 + return nil, fmt.Errorf("handle does not match that declared in DID document") 191 + } 192 + return ident, nil 193 + } 194 + 195 + func (d *CacheDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) { 196 + handle, err := a.AsHandle() 197 + if nil == err { // if not an error, is a handle 198 + return d.LookupHandle(ctx, handle) 199 + } 200 + did, err := a.AsDID() 201 + if nil == err { // if not an error, is a DID 202 + return d.LookupDID(ctx, did) 203 + } 204 + return nil, fmt.Errorf("at-identifier neither a Handle nor a DID") 205 + }
+2 -2
atproto/identity/cmd/atp-id/main.go
··· 50 50 } 51 51 fmt.Printf("valid at-identifier syntax: %s\n", id) 52 52 53 - ncat := identity.NewBasicCatalog("https://plc.directory") 53 + ndir := identity.NewBasicDirectory("https://plc.directory") 54 54 55 - acc, err := ncat.Lookup(ctx, *id) 55 + acc, err := ndir.Lookup(ctx, *id) 56 56 if err != nil { 57 57 return err 58 58 }
+5 -5
atproto/identity/identity.go
··· 21 21 // - local in-memory caching layer to reduce network hits 22 22 // - API client, which just makes requests to PDS (or other remote service) 23 23 // - client for shared network cache (eg, Redis) 24 - type Catalog interface { 24 + type Directory interface { 25 25 LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) 26 26 LookupDID(ctx context.Context, d syntax.DID) (*Identity, error) 27 27 Lookup(ctx context.Context, i syntax.AtIdentifier) (*Identity, error) ··· 39 39 40 40 var DefaultPLCURL = "https://plc.directory" 41 41 42 - // Returns a reasonable default Catalog implementation for most use cases 43 - func DefaultCatalog() Catalog { 44 - naive := NewBasicCatalog(DefaultPLCURL) 45 - cached := NewCacheCatalog(&naive) 42 + // Returns a reasonable default Directory implementation for most use cases 43 + func DefaultDirectory() Directory { 44 + naive := NewBasicDirectory(DefaultPLCURL) 45 + cached := NewCacheDirectory(&naive) 46 46 return &cached 47 47 } 48 48
+14 -14
atproto/identity/live_test.go
··· 10 10 ) 11 11 12 12 // NOTE: this hits the open internet! marked as skip below by default 13 - func testCatalogLive(t *testing.T, c Catalog) { 13 + func testDirectoryLive(t *testing.T, d Directory) { 14 14 assert := assert.New(t) 15 15 ctx := context.Background() 16 16 ··· 18 18 did := syntax.DID("did:plc:ewvi7nxzyoun6zhxrhs64oiz") 19 19 pds := "https://bsky.social" 20 20 21 - resp, err := c.LookupHandle(ctx, handle) 21 + resp, err := d.LookupHandle(ctx, handle) 22 22 assert.NoError(err) 23 23 assert.Equal(handle, resp.Handle) 24 24 assert.Equal(did, resp.DID) ··· 30 30 assert.NoError(err) 31 31 assert.NotNil(pk) 32 32 33 - resp, err = c.LookupDID(ctx, did) 33 + resp, err = d.LookupDID(ctx, did) 34 34 assert.NoError(err) 35 35 assert.Equal(handle, resp.Handle) 36 36 assert.Equal(did, resp.DID) 37 37 assert.Equal(pds, resp.PDSEndpoint()) 38 38 39 - _, err = c.LookupHandle(ctx, syntax.Handle("fake-dummy-no-resolve.atproto.com")) 39 + _, err = d.LookupHandle(ctx, syntax.Handle("fake-dummy-no-resolve.atproto.com")) 40 40 assert.Equal(ErrHandleNotFound, err) 41 41 42 - _, err = c.LookupDID(ctx, syntax.DID("did:web:fake-dummy-no-resolve.atproto.com")) 42 + _, err = d.LookupDID(ctx, syntax.DID("did:web:fake-dummy-no-resolve.atproto.com")) 43 43 assert.Equal(ErrDIDNotFound, err) 44 44 45 - _, err = c.LookupDID(ctx, syntax.DID("did:plc:fake-dummy-no-resolve.atproto.com")) 45 + _, err = d.LookupDID(ctx, syntax.DID("did:plc:fake-dummy-no-resolve.atproto.com")) 46 46 assert.Equal(ErrDIDNotFound, err) 47 47 48 - _, err = c.LookupHandle(ctx, syntax.Handle("handle.invalid")) 48 + _, err = d.LookupHandle(ctx, syntax.Handle("handle.invalid")) 49 49 assert.Error(err) 50 50 } 51 51 52 - func TestBasicCatalog(t *testing.T) { 52 + func TestBasicDirectory(t *testing.T) { 53 53 // XXX: t.Skip("skipping live network test") 54 - c := NewBasicCatalog(DefaultPLCURL) 55 - testCatalogLive(t, &c) 54 + d := NewBasicDirectory(DefaultPLCURL) 55 + testDirectoryLive(t, &d) 56 56 } 57 57 58 - func TestCacheCatalog(t *testing.T) { 58 + func TestCacheDirectory(t *testing.T) { 59 59 // XXX: t.Skip("skipping live network test") 60 - inner := NewBasicCatalog(DefaultPLCURL) 61 - c := NewCacheCatalog(&inner) 60 + inner := NewBasicDirectory(DefaultPLCURL) 61 + d := NewCacheDirectory(&inner) 62 62 for i := 0; i < 3; i = i + 1 { 63 - testCatalogLive(t, &c) 63 + testDirectoryLive(t, &d) 64 64 } 65 65 }
-63
atproto/identity/mock_catalog.go
··· 1 - package identity 2 - 3 - import ( 4 - "context" 5 - "fmt" 6 - 7 - "github.com/bluesky-social/indigo/atproto/syntax" 8 - ) 9 - 10 - // A fake identity catalog, for use in tests 11 - // TODO: should probably move this to a 'mockcatalog' sub-package? 12 - type MockCatalog struct { 13 - Handles map[syntax.Handle]syntax.DID 14 - Identities map[syntax.DID]Identity 15 - } 16 - 17 - var _ Catalog = (*MockCatalog)(nil) 18 - 19 - func NewMockCatalog() MockCatalog { 20 - return MockCatalog{ 21 - Handles: make(map[syntax.Handle]syntax.DID), 22 - Identities: make(map[syntax.DID]Identity), 23 - } 24 - } 25 - 26 - func (c *MockCatalog) Insert(ident Identity) { 27 - if !ident.Handle.IsInvalidHandle() { 28 - c.Handles[ident.Handle] = ident.DID 29 - } 30 - c.Identities[ident.DID] = ident 31 - } 32 - 33 - func (c *MockCatalog) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) { 34 - did, ok := c.Handles[h] 35 - if !ok { 36 - return nil, ErrHandleNotFound 37 - } 38 - ident, ok := c.Identities[did] 39 - if !ok { 40 - return nil, ErrDIDNotFound 41 - } 42 - return &ident, nil 43 - } 44 - 45 - func (c *MockCatalog) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) { 46 - ident, ok := c.Identities[did] 47 - if !ok { 48 - return nil, ErrDIDNotFound 49 - } 50 - return &ident, nil 51 - } 52 - 53 - func (c *MockCatalog) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) { 54 - handle, err := a.AsHandle() 55 - if nil == err { // if not an error, is a Handle 56 - return c.LookupHandle(ctx, handle) 57 - } 58 - did, err := a.AsDID() 59 - if nil == err { // if not an error, is a DID 60 - return c.LookupDID(ctx, did) 61 - } 62 - return nil, fmt.Errorf("at-identifier neither a Handle nor a DID") 63 - }
+3 -3
atproto/identity/mock_catalog_test.go atproto/identity/mock_directory_test.go
··· 9 9 "github.com/stretchr/testify/assert" 10 10 ) 11 11 12 - func TestMockCatalog(t *testing.T) { 12 + func TestMockDirectory(t *testing.T) { 13 13 var err error 14 14 assert := assert.New(t) 15 15 ctx := context.Background() 16 - c := NewMockCatalog() 16 + c := NewMockDirectory() 17 17 id1 := Identity{ 18 18 DID: syntax.DID("did:plc:abc111"), 19 19 Handle: syntax.Handle("handle.example.com"), ··· 27 27 Handle: syntax.Handle("handle3.example.com"), 28 28 } 29 29 30 - // first, empty catalog 30 + // first, empty directory 31 31 _, err = c.LookupHandle(ctx, syntax.Handle("handle.example.com")) 32 32 assert.Equal(ErrHandleNotFound, err) 33 33 _, err = c.LookupDID(ctx, syntax.DID("did:plc:abc123"))
+63
atproto/identity/mock_directory.go
··· 1 + package identity 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + 7 + "github.com/bluesky-social/indigo/atproto/syntax" 8 + ) 9 + 10 + // A fake identity directory , for use in tests 11 + // TODO: should probably move this to a 'mockdirectory' sub-package? 12 + type MockDirectory struct { 13 + Handles map[syntax.Handle]syntax.DID 14 + Identities map[syntax.DID]Identity 15 + } 16 + 17 + var _ Directory = (*MockDirectory)(nil) 18 + 19 + func NewMockDirectory() MockDirectory { 20 + return MockDirectory{ 21 + Handles: make(map[syntax.Handle]syntax.DID), 22 + Identities: make(map[syntax.DID]Identity), 23 + } 24 + } 25 + 26 + func (d *MockDirectory) Insert(ident Identity) { 27 + if !ident.Handle.IsInvalidHandle() { 28 + d.Handles[ident.Handle] = ident.DID 29 + } 30 + d.Identities[ident.DID] = ident 31 + } 32 + 33 + func (d *MockDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) { 34 + did, ok := d.Handles[h] 35 + if !ok { 36 + return nil, ErrHandleNotFound 37 + } 38 + ident, ok := d.Identities[did] 39 + if !ok { 40 + return nil, ErrDIDNotFound 41 + } 42 + return &ident, nil 43 + } 44 + 45 + func (d *MockDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) { 46 + ident, ok := d.Identities[did] 47 + if !ok { 48 + return nil, ErrDIDNotFound 49 + } 50 + return &ident, nil 51 + } 52 + 53 + func (d *MockDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) { 54 + handle, err := a.AsHandle() 55 + if nil == err { // if not an error, is a Handle 56 + return d.LookupHandle(ctx, handle) 57 + } 58 + did, err := a.AsDID() 59 + if nil == err { // if not an error, is a DID 60 + return d.LookupDID(ctx, did) 61 + } 62 + return nil, fmt.Errorf("at-identifier neither a Handle nor a DID") 63 + }