Skip to content

Commit

Permalink
re-organize identity package files (bluesky-social#871)
Browse files Browse the repository at this point in the history
This is a no-op, just shuffling code around between files.
  • Loading branch information
bnewbold authored Dec 6, 2024
2 parents 1cdcd10 + 28d2ee4 commit 5ee8937
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 95 deletions.
20 changes: 0 additions & 20 deletions atproto/identity/did.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,6 @@ import (
"github.com/bluesky-social/indigo/atproto/syntax"
)

type DIDDocument struct {
DID syntax.DID `json:"id"`
AlsoKnownAs []string `json:"alsoKnownAs,omitempty"`
VerificationMethod []DocVerificationMethod `json:"verificationMethod,omitempty"`
Service []DocService `json:"service,omitempty"`
}

type DocVerificationMethod struct {
ID string `json:"id"`
Type string `json:"type"`
Controller string `json:"controller"`
PublicKeyMultibase string `json:"publicKeyMultibase"`
}

type DocService struct {
ID string `json:"id"`
Type string `json:"type"`
ServiceEndpoint string `json:"serviceEndpoint"`
}

// WARNING: this does *not* bi-directionally verify account metadata; it only implements direct DID-to-DID-document lookup for the supported DID methods, and parses the resulting DID Doc into an Identity struct
func (d *BaseDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error) {
start := time.Now()
Expand Down
25 changes: 25 additions & 0 deletions atproto/identity/diddoc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package identity

import (
"github.com/bluesky-social/indigo/atproto/syntax"
)

type DIDDocument struct {
DID syntax.DID `json:"id"`
AlsoKnownAs []string `json:"alsoKnownAs,omitempty"`
VerificationMethod []DocVerificationMethod `json:"verificationMethod,omitempty"`
Service []DocService `json:"service,omitempty"`
}

type DocVerificationMethod struct {
ID string `json:"id"`
Type string `json:"type"`
Controller string `json:"controller"`
PublicKeyMultibase string `json:"publicKeyMultibase"`
}

type DocService struct {
ID string `json:"id"`
Type string `json:"type"`
ServiceEndpoint string `json:"serviceEndpoint"`
}
File renamed without changes.
81 changes: 81 additions & 0 deletions atproto/identity/directory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package identity

import (
"context"
"errors"
"net"
"net/http"
"time"

"github.com/bluesky-social/indigo/atproto/syntax"
)

// API for doing account lookups by DID or handle, with bi-directional verification handled automatically. Almost all atproto services and clients should use an implementation of this interface instead of resolving handles or DIDs separately
//
// Handles which fail to resolve, or don't match DID alsoKnownAs, are an error. DIDs which resolve but the handle does not resolve back to the DID return an Identity where the Handle is the special `handle.invalid` value.
//
// Some example implementations of this interface could be:
// - basic direct resolution on every call
// - local in-memory caching layer to reduce network hits
// - API client, which just makes requests to PDS (or other remote service)
// - client for shared network cache (eg, Redis)
type Directory interface {
LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)
LookupDID(ctx context.Context, d syntax.DID) (*Identity, error)
Lookup(ctx context.Context, i syntax.AtIdentifier) (*Identity, error)

// Flushes any cache of the indicated identifier. If directory is not using caching, can ignore this.
Purge(ctx context.Context, i syntax.AtIdentifier) error
}

// Indicates that handle resolution failed. A wrapped error may provide more context. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleResolutionFailed = errors.New("handle resolution failed")

// Indicates that resolution process completed successfully, but handle does not exist. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleNotFound = errors.New("handle not found")

// Indicates that resolution process completed successfully, handle mapped to a different DID. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleMismatch = errors.New("handle/DID mismatch")

// Indicates that DID document did not include any handle ("alsoKnownAs"). This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleNotDeclared = errors.New("DID document did not declare a handle")

// Handle top-level domain (TLD) is one of the special "Reserved" suffixes, and not allowed for atproto use
var ErrHandleReservedTLD = errors.New("handle top-level domain is disallowed")

// Indicates that resolution process completed successfully, but the DID does not exist.
var ErrDIDNotFound = errors.New("DID not found")

// Indicates that DID resolution process failed. A wrapped error may provide more context.
var ErrDIDResolutionFailed = errors.New("DID resolution failed")

// Indicates that DID document did not include a public key with the specified ID
var ErrKeyNotDeclared = errors.New("DID document did not declare a relevant public key")

var DefaultPLCURL = "https://plc.directory"

// Returns a reasonable Directory implementation for applications
func DefaultDirectory() Directory {
base := BaseDirectory{
PLCURL: DefaultPLCURL,
HTTPClient: http.Client{
Timeout: time.Second * 10,
Transport: &http.Transport{
// would want this around 100ms for services doing lots of handle resolution. Impacts PLC connections as well, but not too bad.
IdleConnTimeout: time.Millisecond * 1000,
MaxIdleConns: 100,
},
},
Resolver: net.Resolver{
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{Timeout: time.Second * 3}
return d.DialContext(ctx, network, address)
},
},
TryAuthoritativeDNS: true,
// primary Bluesky PDS instance only supports HTTP resolution method
SkipDNSDomainSuffixes: []string{".bsky.social"},
}
cached := NewCacheDirectory(&base, 250_000, time.Hour*24, time.Minute*2, time.Minute*5)
return &cached
}
75 changes: 0 additions & 75 deletions atproto/identity/identity.go
Original file line number Diff line number Diff line change
@@ -1,91 +1,16 @@
package identity

import (
"context"
"errors"
"fmt"
"net"
"net/http"
"net/url"
"strings"
"time"

"github.com/bluesky-social/indigo/atproto/crypto"
"github.com/bluesky-social/indigo/atproto/syntax"

"github.com/mr-tron/base58"
)

// API for doing account lookups by DID or handle, with bi-directional verification handled automatically. Almost all atproto services and clients should use an implementation of this interface instead of resolving handles or DIDs separately
//
// Handles which fail to resolve, or don't match DID alsoKnownAs, are an error. DIDs which resolve but the handle does not resolve back to the DID return an Identity where the Handle is the special `handle.invalid` value.
//
// Some example implementations of this interface could be:
// - basic direct resolution on every call
// - local in-memory caching layer to reduce network hits
// - API client, which just makes requests to PDS (or other remote service)
// - client for shared network cache (eg, Redis)
type Directory interface {
LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)
LookupDID(ctx context.Context, d syntax.DID) (*Identity, error)
Lookup(ctx context.Context, i syntax.AtIdentifier) (*Identity, error)

// Flushes any cache of the indicated identifier. If directory is not using caching, can ignore this.
Purge(ctx context.Context, i syntax.AtIdentifier) error
}

// Indicates that handle resolution failed. A wrapped error may provide more context. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleResolutionFailed = errors.New("handle resolution failed")

// Indicates that resolution process completed successfully, but handle does not exist. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleNotFound = errors.New("handle not found")

// Indicates that resolution process completed successfully, handle mapped to a different DID. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleMismatch = errors.New("handle/DID mismatch")

// Indicates that DID document did not include any handle ("alsoKnownAs"). This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleNotDeclared = errors.New("DID document did not declare a handle")

// Handle top-level domain (TLD) is one of the special "Reserved" suffixes, and not allowed for atproto use
var ErrHandleReservedTLD = errors.New("handle top-level domain is disallowed")

// Indicates that resolution process completed successfully, but the DID does not exist.
var ErrDIDNotFound = errors.New("DID not found")

// Indicates that DID resolution process failed. A wrapped error may provide more context.
var ErrDIDResolutionFailed = errors.New("DID resolution failed")

// Indicates that DID document did not include a public key with the specified ID
var ErrKeyNotDeclared = errors.New("DID document did not declare a relevant public key")

var DefaultPLCURL = "https://plc.directory"

// Returns a reasonable Directory implementation for applications
func DefaultDirectory() Directory {
base := BaseDirectory{
PLCURL: DefaultPLCURL,
HTTPClient: http.Client{
Timeout: time.Second * 10,
Transport: &http.Transport{
// would want this around 100ms for services doing lots of handle resolution. Impacts PLC connections as well, but not too bad.
IdleConnTimeout: time.Millisecond * 1000,
MaxIdleConns: 100,
},
},
Resolver: net.Resolver{
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{Timeout: time.Second * 3}
return d.DialContext(ctx, network, address)
},
},
TryAuthoritativeDNS: true,
// primary Bluesky PDS instance only supports HTTP resolution method
SkipDNSDomainSuffixes: []string{".bsky.social"},
}
cached := NewCacheDirectory(&base, 250_000, time.Hour*24, time.Minute*2, time.Minute*5)
return &cached
}

// Represents an atproto identity. Could be a regular user account, or a service account (eg, feed generator)
type Identity struct {
DID syntax.DID
Expand Down

0 comments on commit 5ee8937

Please sign in to comment.