this repo has no description
0
fork

Configure Feed

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

identity: cleanup interfaces, add some docs

+48 -16
+32 -16
atproto/identity/identity.go
··· 4 4 "context" 5 5 "errors" 6 6 "fmt" 7 + "net" 8 + "net/http" 9 + "net/url" 7 10 "strings" 8 11 9 12 "github.com/bluesky-social/indigo/atproto/crypto" ··· 37 40 // Indicates that resolution process completed successfully, but the DID does not exist. 38 41 var ErrDIDNotFound = errors.New("DID not found") 39 42 43 + var ErrKeyNotFound = errors.New("identity has no public repo signing key") 44 + 40 45 var DefaultPLCURL = "https://plc.directory" 41 46 42 47 // Returns a reasonable default Directory implementation for most use cases 43 48 func DefaultDirectory() Directory { 44 - naive := NewBaseDirectory(DefaultPLCURL) 45 - cached := NewCacheDirectory(&naive) 49 + base := BaseDirectory{ 50 + PLCURL: DefaultPLCURL, 51 + HTTPClient: http.DefaultClient, 52 + Resolver: net.DefaultResolver, 53 + } 54 + cached := NewCacheDirectory(&base) 46 55 return &cached 47 56 } 48 57 ··· 51 60 DID syntax.DID 52 61 53 62 // Handle/DID mapping must be bi-directionally verified. If that fails, the Handle should be the special 'handle.invalid' value 54 - // TODO: should we make this nullable, instead of 'handle.invalid'? 55 63 Handle syntax.Handle 56 64 57 - // These fields represent a parsed subset of a DID document. They are all nullable. 58 - // TODO: should we just embed DIDDocument here? 65 + // These fields represent a parsed subset of a DID document. They are all nullable. Note that the services and keys maps do not preserve order, so they don't exactly round-trip DID documents. 59 66 AlsoKnownAs []string 60 - // TODO: this doesn't preserve order (doesn't round-trip) 61 - Services map[string]Service 62 - // TODO: this doesn't preserve order (doesn't round-trip) 63 - Keys map[string]Key 67 + Services map[string]Service 68 + Keys map[string]Key 64 69 65 - // If a valid atproto repo signing public key was parsed, it can be cached here. This is nullable/optional. Calling code should call PublicKey() instead of accessing this member. 70 + // If a valid atproto repo signing public key was parsed, it can be cached here. This is a nullable/optional field (crypto.PublicKey is an interface). Calling code should use [Identity.PublicKey] instead of accessing this member. 66 71 ParsedPublicKey crypto.PublicKey 67 72 } 68 73 ··· 76 81 URL string 77 82 } 78 83 84 + // Extracts the information relevant to atproto from an arbitrary DID document. 85 + // 86 + // Always returns an invalid Handle field; calling code should only populate that field if it has been bi-directionally verified. 79 87 func ParseIdentity(doc *DIDDocument) Identity { 80 88 keys := make(map[string]Key, len(doc.VerificationMethod)) 81 89 for _, vm := range doc.VerificationMethod { ··· 122 130 } 123 131 } 124 132 125 - // Identifiers the atproto repo signing public key, specifically, out of any keys associated with this identity. 133 + // Identifies and parses the atproto repo signing public key, specifically, out of any keys associated with this identity. 126 134 // 127 - // Returns an error if there is no key. Note that 'crypto.PublicKey' is an interface, not a concrete type. 135 + // Returns [ErrKeyNotFound] if there is no such key. 136 + // 137 + // Note that [crypto.PublicKey] is an interface, not a concrete type. 128 138 func (i *Identity) PublicKey() (crypto.PublicKey, error) { 129 139 if i.ParsedPublicKey != nil { 130 140 return i.ParsedPublicKey, nil ··· 134 144 } 135 145 k, ok := i.Keys["atproto"] 136 146 if !ok { 137 - return nil, fmt.Errorf("identity has no atproto public key attached") 147 + return nil, ErrKeyNotFound 138 148 } 139 149 switch k.Type { 140 150 case "Multikey": ··· 162 172 } 163 173 } 164 174 165 - // The home PDS endpoint for this account, if one is included in identity metadata (returns empty string if not found). The endpoint will be an HTTP URL with method, hostname, and optional port, but no path segments. 175 + // The home PDS endpoint for this account, if one is included in identity metadata (returns empty string if not found). 176 + // 177 + // The endpoint should be an HTTP URL with method, hostname, and optional port, and (usually) no path segments. 166 178 func (i *Identity) PDSEndpoint() string { 167 179 if i.Services == nil { 168 180 return "" 169 181 } 170 - atp, ok := i.Services["atproto_pds"] 182 + endpoint, ok := i.Services["atproto_pds"] 171 183 if !ok { 172 184 return "" 173 185 } 174 - return atp.URL 186 + _, err := url.Parse(endpoint.URL) 187 + if err != nil { 188 + return "" 189 + } 190 + return endpoint.URL 175 191 } 176 192 177 193 // Returns an atproto handle from the alsoKnownAs URI list for this identifier. Returns an error if there is no handle, or if an at:// URI failes to parse as a handle.
+16
atproto/identity/testdata/did_web_doc.json
··· 1 + { 2 + "@context": [ 3 + "https://www.w3.org/ns/did/v1" 4 + ], 5 + "id": "did:web:discover.bsky.social", 6 + "alsoKnownAs": [ ], 7 + "authentication": null, 8 + "verificationMethod": [ ], 9 + "service": [ 10 + { 11 + "id": "#bsky_fg", 12 + "type": "BskyFeedGenerator", 13 + "serviceEndpoint": "https://discover.bsky.social" 14 + } 15 + ] 16 + }