github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/profile/id.go (about)

     1  package profile
     2  
     3  import (
     4  	"encoding/hex"
     5  	"encoding/json"
     6  	"fmt"
     7  	"strings"
     8  
     9  	peer "github.com/libp2p/go-libp2p-core/peer"
    10  	"github.com/qri-io/doggos"
    11  )
    12  
    13  // AnonUsername generates an anonymous username from a base58-encoded peer
    14  // identifier
    15  func AnonUsername(b58ID string) string {
    16  	return doggos.DoggoNick(b58ID)
    17  }
    18  
    19  // ID is a distinct thing form a peer.ID. They are *NOT* meant to be
    20  // interchangable, but the mechanics of peer.ID & profile.ID are similar
    21  type ID peer.ID
    22  
    23  // String converts a profileID to a string for debugging
    24  func (id ID) String() string {
    25  	bytes := []byte(id)
    26  	return fmt.Sprintf("profile.ID{%s}", hex.EncodeToString(bytes))
    27  }
    28  
    29  // Encode converts a profileID into a base58 encoded string
    30  func (id ID) Encode() string {
    31  	return peer.ID(id).Pretty()
    32  }
    33  
    34  // Empty returns whether the id is empty
    35  func (id ID) Empty() bool {
    36  	return id.Encode() == ""
    37  }
    38  
    39  // Validate validates the profileID, returning an error if it is invalid
    40  func (id ID) Validate() error {
    41  	if err := peer.ID(id).Validate(); err != nil {
    42  		return err
    43  	}
    44  	// RSA based ID
    45  	b64str := id.Encode()
    46  	if strings.HasPrefix(b64str, "Qm") {
    47  		return nil
    48  	}
    49  	if strings.HasPrefix(b64str, "9t") {
    50  		return fmt.Errorf("profile.ID invalid, was double encoded as %q. do not pass a base64 encoded string, instead use IDB58Decode(b64encodedID)", b64str)
    51  	}
    52  	// ED based ID
    53  	if strings.HasPrefix(b64str, "12D") {
    54  		return nil
    55  	}
    56  	return fmt.Errorf("profile.ID invalid, encodes to %q", b64str)
    57  }
    58  
    59  // MarshalJSON encodes the ID for json marshalling
    60  func (id ID) MarshalJSON() ([]byte, error) {
    61  	return json.Marshal(id.Encode())
    62  }
    63  
    64  // UnmarshalJSON unmarshals an id from json
    65  func (id *ID) UnmarshalJSON(data []byte) (err error) {
    66  	var str string
    67  	if err := json.Unmarshal(data, &str); err != nil {
    68  		return err
    69  	}
    70  	*id, err = IDB58Decode(str)
    71  	return
    72  }
    73  
    74  // MarshalYAML encodes the ID for yaml marshalling
    75  func (id *ID) MarshalYAML() (interface{}, error) {
    76  	return id.Encode(), nil
    77  }
    78  
    79  // UnmarshalYAML unmarshals an id from yaml
    80  func (id *ID) UnmarshalYAML(unmarshal func(interface{}) error) (err error) {
    81  	var str string
    82  	if err := unmarshal(&str); err != nil {
    83  		return err
    84  	}
    85  	*id, err = IDB58Decode(str)
    86  	return
    87  }
    88  
    89  // IDRawByteString constructs an ID from a raw byte string. No base58 decoding happens.
    90  // Should only be used in tests
    91  func IDRawByteString(data string) ID {
    92  	return ID(data)
    93  }
    94  
    95  // IDFromPeerID type casts a peer.ID from ipfs into an ID
    96  func IDFromPeerID(pid peer.ID) ID {
    97  	return ID(pid)
    98  }
    99  
   100  // IDB58Decode decodes a base58 string into a profile.ID
   101  func IDB58Decode(proid string) (ID, error) {
   102  	pid, err := peer.IDB58Decode(proid)
   103  	return ID(pid), err
   104  }
   105  
   106  // IDB58DecodeOrEmpty decodes an ID, or returns an empty ID if decoding fails
   107  func IDB58DecodeOrEmpty(proid string) ID {
   108  	pid, err := peer.IDB58Decode(proid)
   109  	if err != nil {
   110  		pid = ""
   111  	}
   112  	return ID(pid)
   113  }
   114  
   115  // IDB58MustDecode panics if an ID doesn't decode. useful for testing
   116  func IDB58MustDecode(proid string) ID {
   117  	pid, err := peer.IDB58Decode(proid)
   118  	if err != nil {
   119  		panic(proid + " " + err.Error())
   120  	}
   121  	return ID(pid)
   122  }