diff options
Diffstat (limited to 'identity/bare.go')
-rw-r--r-- | identity/bare.go | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/identity/bare.go b/identity/bare.go new file mode 100644 index 00000000..6af794dd --- /dev/null +++ b/identity/bare.go @@ -0,0 +1,204 @@ +package identity + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "strings" + + "github.com/MichaelMure/git-bug/repository" + "github.com/MichaelMure/git-bug/util/lamport" + "github.com/MichaelMure/git-bug/util/text" + "github.com/MichaelMure/git-bug/util/timestamp" +) + +var _ Interface = &Bare{} + +// Bare is a very minimal identity, designed to be fully embedded directly along +// other data. +// +// in particular, this identity is designed to be compatible with the handling of +// identities in the early version of git-bug. +type Bare struct { + id string + name string + email string + login string + avatarUrl string +} + +func NewBare(name string, email string) *Bare { + return &Bare{name: name, email: email} +} + +func NewBareFull(name string, email string, login string, avatarUrl string) *Bare { + return &Bare{name: name, email: email, login: login, avatarUrl: avatarUrl} +} + +type bareIdentityJSON struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Login string `json:"login,omitempty"` + AvatarUrl string `json:"avatar_url,omitempty"` +} + +func (i *Bare) MarshalJSON() ([]byte, error) { + return json.Marshal(bareIdentityJSON{ + Name: i.name, + Email: i.email, + Login: i.login, + AvatarUrl: i.avatarUrl, + }) +} + +func (i *Bare) UnmarshalJSON(data []byte) error { + aux := bareIdentityJSON{} + + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + i.name = aux.Name + i.email = aux.Email + i.login = aux.Login + i.avatarUrl = aux.AvatarUrl + + return nil +} + +// Id return the Identity identifier +func (i *Bare) Id() string { + // We don't have a proper ID at hand, so let's hash all the data to get one. + // Hopefully the + + if i.id != "" { + return i.id + } + + data, err := json.Marshal(i) + if err != nil { + panic(err) + } + + h := fmt.Sprintf("%x", sha256.New().Sum(data)[:16]) + i.id = string(h) + + return i.id +} + +// HumanId return the Identity identifier truncated for human consumption +func (i *Bare) HumanId() string { + return FormatHumanID(i.Id()) +} + +// Name return the last version of the name +func (i *Bare) Name() string { + return i.name +} + +// Email return the last version of the email +func (i *Bare) Email() string { + return i.email +} + +// Login return the last version of the login +func (i *Bare) Login() string { + return i.login +} + +// AvatarUrl return the last version of the Avatar URL +func (i *Bare) AvatarUrl() string { + return i.avatarUrl +} + +// Keys return the last version of the valid keys +func (i *Bare) Keys() []Key { + return []Key{} +} + +// ValidKeysAtTime return the set of keys valid at a given lamport time +func (i *Bare) ValidKeysAtTime(time lamport.Time) []Key { + return []Key{} +} + +// DisplayName return a non-empty string to display, representing the +// identity, based on the non-empty values. +func (i *Bare) DisplayName() string { + switch { + case i.name == "" && i.login != "": + return i.login + case i.name != "" && i.login == "": + return i.name + case i.name != "" && i.login != "": + return fmt.Sprintf("%s (%s)", i.name, i.login) + } + + panic("invalid person data") +} + +// Validate check if the Identity data is valid +func (i *Bare) Validate() error { + if text.Empty(i.name) && text.Empty(i.login) { + return fmt.Errorf("either name or login should be set") + } + + if strings.Contains(i.name, "\n") { + return fmt.Errorf("name should be a single line") + } + + if !text.Safe(i.name) { + return fmt.Errorf("name is not fully printable") + } + + if strings.Contains(i.login, "\n") { + return fmt.Errorf("login should be a single line") + } + + if !text.Safe(i.login) { + return fmt.Errorf("login is not fully printable") + } + + if strings.Contains(i.email, "\n") { + return fmt.Errorf("email should be a single line") + } + + if !text.Safe(i.email) { + return fmt.Errorf("email is not fully printable") + } + + if i.avatarUrl != "" && !text.ValidUrl(i.avatarUrl) { + return fmt.Errorf("avatarUrl is not a valid URL") + } + + return nil +} + +// Write the identity into the Repository. In particular, this ensure that +// the Id is properly set. +func (i *Bare) Commit(repo repository.ClockedRepo) error { + // Nothing to do, everything is directly embedded + return nil +} + +// If needed, write the identity into the Repository. In particular, this +// ensure that the Id is properly set. +func (i *Bare) CommitAsNeeded(repo repository.ClockedRepo) error { + // Nothing to do, everything is directly embedded + return nil +} + +// IsProtected return true if the chain of git commits started to be signed. +// If that's the case, only signed commit with a valid key for this identity can be added. +func (i *Bare) IsProtected() bool { + return false +} + +// LastModificationLamportTime return the Lamport time at which the last version of the identity became valid. +func (i *Bare) LastModificationLamport() lamport.Time { + return 0 +} + +// LastModification return the timestamp at which the last version of the identity became valid. +func (i *Bare) LastModification() timestamp.Timestamp { + return 0 +} |