github.com/status-im/status-go@v1.1.0/protocol/messenger_identity.go (about) 1 package protocol 2 3 import ( 4 "errors" 5 "fmt" 6 "runtime" 7 "strings" 8 "unicode/utf8" 9 10 utils "github.com/status-im/status-go/common" 11 "github.com/status-im/status-go/multiaccounts/settings" 12 "github.com/status-im/status-go/protocol/encryption/multidevice" 13 "github.com/status-im/status-go/server" 14 ) 15 16 const ( 17 maxBioLength = 240 18 ) 19 20 var ErrInvalidBioLength = errors.New("invalid bio length") 21 var ErrDisplayNameDupeOfCommunityMember = errors.New("display name duplicates on of community members") 22 23 func (m *Messenger) SetDisplayName(displayName string) error { 24 currDisplayName, err := m.settings.DisplayName() 25 if err != nil { 26 return err 27 } 28 29 if utils.IsENSName(displayName) || currDisplayName == displayName { 30 return nil // Do nothing 31 } 32 33 if err = utils.ValidateDisplayName(&displayName); err != nil { 34 return err 35 } 36 37 isDupe, err := m.IsDisplayNameDupeOfCommunityMember(displayName) 38 if err != nil { 39 return err 40 } 41 42 if isDupe { 43 return ErrDisplayNameDupeOfCommunityMember 44 } 45 46 m.account.Name = displayName 47 err = m.multiAccounts.UpdateDisplayName(m.account.KeyUID, displayName) 48 if err != nil { 49 return err 50 } 51 52 err = m.settings.SaveSettingField(settings.DisplayName, displayName) 53 if err != nil { 54 return err 55 } 56 57 err = m.UpdateKeypairName(m.account.KeyUID, displayName) 58 if err != nil { 59 return err 60 } 61 62 err = m.resetLastPublishedTimeForChatIdentity() 63 if err != nil { 64 return err 65 } 66 67 return m.publishContactCode() 68 } 69 70 func (m *Messenger) SaveSyncDisplayName(displayName string, clock uint64) error { 71 err := m.settings.SaveSyncSetting(settings.DisplayName, displayName, clock) 72 if err != nil { 73 return err 74 } 75 76 preferredName, err := m.settings.GetPreferredUsername() 77 if err != nil { 78 return err 79 } 80 81 preferredNameClock, err := m.settings.GetSettingLastSynced(settings.PreferredName) 82 if err != nil { 83 return err 84 } 85 // When either the display name or preferred name changes, m.account.Name should be updated. 86 // However, a race condition can occur during BackupData, where m.account.Name could be incorrectly updated. 87 // The final value of m.account.Name depends on which backup message(BackedUpProfile/BackedUpSettings) arrives later. 88 // So we should check the clock of the preferred name and only update m.account.Name if it's older than the display name. 89 // Yet even if the preferred name clock is older, but the preferred name was empty, we should still update m.account.Name. 90 91 if preferredNameClock < clock || preferredName == "" { 92 m.account.Name = displayName 93 return m.multiAccounts.SaveAccount(*m.account) 94 } 95 return nil 96 } 97 98 func ValidateBio(bio *string) error { 99 if utf8.RuneCountInString(*bio) > maxBioLength { 100 return ErrInvalidBioLength 101 } 102 return nil 103 } 104 105 func (m *Messenger) SetBio(bio string) error { 106 currentBio, err := m.settings.Bio() 107 if err != nil { 108 return err 109 } 110 111 if currentBio == bio { 112 return nil // Do nothing 113 } 114 115 if err = ValidateBio(&bio); err != nil { 116 return err 117 } 118 119 if err = m.settings.SaveSettingField(settings.Bio, bio); err != nil { 120 return err 121 } 122 123 if err = m.resetLastPublishedTimeForChatIdentity(); err != nil { 124 return err 125 } 126 127 return m.publishContactCode() 128 } 129 130 func (m *Messenger) setInstallationHostname() error { 131 imd, err := m.getOurInstallationMetadata() 132 if err != nil { 133 return err 134 } 135 136 // If the name and device are already set, don't do anything 137 if len(imd.Name) != 0 && len(imd.DeviceType) != 0 { 138 return nil 139 } 140 141 if len(imd.Name) == 0 { 142 deviceName, err := m.settings.DeviceName() 143 if err != nil { 144 return err 145 } 146 if deviceName != "" { 147 imd.Name = deviceName 148 } else { 149 hn, err := server.GetDeviceName() 150 if err != nil { 151 return err 152 } 153 // NOTE: imd.Name is always empty in this else branch, which leads to the 154 // result of Sprintf having a trailing whitespace. 155 imd.Name = fmt.Sprintf("%s %s", hn, imd.Name) 156 } 157 } 158 159 if len(imd.DeviceType) == 0 { 160 imd.DeviceType = runtime.GOOS 161 } 162 163 return m.setInstallationMetadata(m.installationID, imd) 164 165 } 166 167 func (m *Messenger) getOurInstallationMetadata() (*multidevice.InstallationMetadata, error) { 168 ourInstallation, ok := m.allInstallations.Load(m.installationID) 169 if !ok { 170 return nil, fmt.Errorf("messenger's installationID is not set or not loadable") 171 } 172 173 if ourInstallation.InstallationMetadata == nil { 174 return new(multidevice.InstallationMetadata), nil 175 } 176 177 return ourInstallation.InstallationMetadata, nil 178 } 179 180 func (m *Messenger) SetInstallationDeviceType(deviceType string) error { 181 if strings.TrimSpace(deviceType) == "" { 182 return errors.New("device type is empty") 183 } 184 185 imd, err := m.getOurInstallationMetadata() 186 if err != nil { 187 return err 188 } 189 190 // If the name is already set, don't do anything 191 if len(imd.DeviceType) != 0 { 192 return nil 193 } 194 195 imd.DeviceType = deviceType 196 return m.setInstallationMetadata(m.installationID, imd) 197 }