porting all github actions from bluesky-social/indigo to tangled CI
at main 4.3 kB view raw
1package identity 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "net" 8 "net/http" 9 10 "github.com/bluesky-social/indigo/atproto/syntax" 11 "golang.org/x/time/rate" 12) 13 14// The zero value ('BaseDirectory{}') is a usable Directory. 15type BaseDirectory struct { 16 // if non-empty, this string should have URL method, hostname, and optional port; it should not have a path or trailing slash 17 PLCURL string 18 // If not nil, this limiter will be used to rate-limit requests to the PLCURL 19 PLCLimiter *rate.Limiter 20 // If not nil, this function will be called inline with DID Web lookups, and can be used to limit the number of requests to a given hostname 21 DIDWebLimitFunc func(ctx context.Context, hostname string) error 22 // HTTP client used for did:web, did:plc, and HTTP (well-known) handle resolution 23 HTTPClient http.Client 24 // DNS resolver used for DNS handle resolution. Calling code can use a custom Dialer to query against a specific DNS server, or re-implement the interface for even more control over the resolution process 25 Resolver net.Resolver 26 // when doing DNS handle resolution, should this resolver attempt re-try against an authoritative nameserver if the first TXT lookup fails? 27 TryAuthoritativeDNS bool 28 // set of handle domain suffixes for for which DNS handle resolution will be skipped 29 SkipDNSDomainSuffixes []string 30 // set of fallback DNS servers (eg, domain registrars) to try as a fallback. each entry should be "ip:port", eg "8.8.8.8:53" 31 FallbackDNSServers []string 32 // skips bi-directional verification of handles when doing DID lookups (eg, `LookupDID`). Does not impact direct resolution (`ResolveHandle`) or handle-specific lookup (`LookupHandle`). 33 // 34 // The intended use-case for this flag is as an optimization for services which do not care about handles, but still want to use the `Directory` interface (instead of `ResolveDID`). For example, relay implementations, or services validating inter-service auth requests. 35 SkipHandleVerification bool 36 // User-Agent header for HTTP requests. Optional (ignored if empty string). 37 UserAgent string 38} 39 40var _ Directory = (*BaseDirectory)(nil) 41var _ Resolver = (*BaseDirectory)(nil) 42 43func (d *BaseDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) { 44 h = h.Normalize() 45 did, err := d.ResolveHandle(ctx, h) 46 if err != nil { 47 return nil, err 48 } 49 doc, err := d.ResolveDID(ctx, did) 50 if err != nil { 51 return nil, err 52 } 53 ident := ParseIdentity(doc) 54 declared, err := ident.DeclaredHandle() 55 if err != nil { 56 return nil, fmt.Errorf("could not verify handle/DID match: %w", err) 57 } 58 // NOTE: DeclaredHandle() returns a normalized handle, and we already normalized 'h' above 59 if declared != h { 60 return nil, fmt.Errorf("%w: %s != %s", ErrHandleMismatch, declared, h) 61 } 62 ident.Handle = declared 63 64 return &ident, nil 65} 66 67func (d *BaseDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) { 68 doc, err := d.ResolveDID(ctx, did) 69 if err != nil { 70 return nil, err 71 } 72 ident := ParseIdentity(doc) 73 if d.SkipHandleVerification { 74 ident.Handle = syntax.HandleInvalid 75 return &ident, nil 76 } 77 declared, err := ident.DeclaredHandle() 78 if errors.Is(err, ErrHandleNotDeclared) { 79 ident.Handle = syntax.HandleInvalid 80 } else if err != nil { 81 return nil, fmt.Errorf("could not parse handle from DID document: %w", err) 82 } else { 83 // if a handle was declared, resolve it 84 resolvedDID, err := d.ResolveHandle(ctx, declared) 85 if err != nil { 86 if errors.Is(err, ErrHandleNotFound) || errors.Is(err, ErrHandleResolutionFailed) { 87 ident.Handle = syntax.HandleInvalid 88 } else { 89 return nil, err 90 } 91 } else if resolvedDID != did { 92 ident.Handle = syntax.HandleInvalid 93 } else { 94 ident.Handle = declared 95 } 96 } 97 98 return &ident, nil 99} 100 101func (d *BaseDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) { 102 handle, err := a.AsHandle() 103 if nil == err { // if *not* an error 104 return d.LookupHandle(ctx, handle) 105 } 106 did, err := a.AsDID() 107 if nil == err { // if *not* an error 108 return d.LookupDID(ctx, did) 109 } 110 return nil, fmt.Errorf("at-identifier neither a Handle nor a DID") 111} 112 113func (d *BaseDirectory) Purge(ctx context.Context, atid syntax.AtIdentifier) error { 114 // BaseDirectory itself does not implement caching 115 return nil 116}