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 }