aboutsummaryrefslogtreecommitdiffstats
path: root/identity/bare.go
diff options
context:
space:
mode:
Diffstat (limited to 'identity/bare.go')
-rw-r--r--identity/bare.go204
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
+}