aboutsummaryrefslogtreecommitdiffstats
path: root/identity
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2020-02-09 01:31:00 +0100
committerGitHub <noreply@github.com>2020-02-09 01:31:00 +0100
commit9e1a987b4d94dc5c2115423ede5954d4faf1d342 (patch)
treee30bb28d55444a7d1e66c8fa8b8ba7d413805473 /identity
parent97bc5ccd229b7b438262a84e3c42783b4d4a82af (diff)
parent9b1aaa032d36e1ac05504916e359f767d1622d9d (diff)
downloadgit-bug-9e1a987b4d94dc5c2115423ede5954d4faf1d342.tar.gz
Merge pull request #294 from MichaelMure/cred-metadata
Cred metadata
Diffstat (limited to 'identity')
-rw-r--r--identity/bare.go45
-rw-r--r--identity/bare_test.go1
-rw-r--r--identity/common.go2
-rw-r--r--identity/identity.go67
-rw-r--r--identity/identity_actions_test.go8
-rw-r--r--identity/identity_stub.go4
-rw-r--r--identity/identity_test.go45
-rw-r--r--identity/interface.go7
-rw-r--r--identity/key.go5
-rw-r--r--identity/version.go40
-rw-r--r--identity/version_test.go3
11 files changed, 115 insertions, 112 deletions
diff --git a/identity/bare.go b/identity/bare.go
index a243f074..a02ec790 100644
--- a/identity/bare.go
+++ b/identity/bare.go
@@ -25,7 +25,6 @@ type Bare struct {
id entity.Id
name string
email string
- login string
avatarUrl string
}
@@ -33,8 +32,8 @@ func NewBare(name string, email string) *Bare {
return &Bare{id: entity.UnsetId, name: name, email: email}
}
-func NewBareFull(name string, email string, login string, avatarUrl string) *Bare {
- return &Bare{id: entity.UnsetId, name: name, email: email, login: login, avatarUrl: avatarUrl}
+func NewBareFull(name string, email string, avatarUrl string) *Bare {
+ return &Bare{id: entity.UnsetId, name: name, email: email, avatarUrl: avatarUrl}
}
func deriveId(data []byte) entity.Id {
@@ -45,7 +44,7 @@ func deriveId(data []byte) entity.Id {
type bareIdentityJSON struct {
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
- Login string `json:"login,omitempty"`
+ Login string `json:"login,omitempty"` // Deprecated, only kept to have the same ID when reading an old value
AvatarUrl string `json:"avatar_url,omitempty"`
}
@@ -53,7 +52,6 @@ func (i *Bare) MarshalJSON() ([]byte, error) {
return json.Marshal(bareIdentityJSON{
Name: i.name,
Email: i.email,
- Login: i.login,
AvatarUrl: i.avatarUrl,
})
}
@@ -70,7 +68,6 @@ func (i *Bare) UnmarshalJSON(data []byte) error {
i.name = aux.Name
i.email = aux.Email
- i.login = aux.Login
i.avatarUrl = aux.AvatarUrl
return nil
@@ -109,45 +106,31 @@ 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{}
+func (i *Bare) Keys() []*Key {
+ return nil
}
// ValidKeysAtTime return the set of keys valid at a given lamport time
-func (i *Bare) ValidKeysAtTime(time lamport.Time) []Key {
- return []Key{}
+func (i *Bare) ValidKeysAtTime(_ lamport.Time) []*Key {
+ return nil
}
// 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")
+ return i.name
}
// 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 text.Empty(i.name) {
+ return fmt.Errorf("name is not set")
}
if strings.Contains(i.name, "\n") {
@@ -158,14 +141,6 @@ func (i *Bare) Validate() error {
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")
}
diff --git a/identity/bare_test.go b/identity/bare_test.go
index 335c8d37..5aa50e40 100644
--- a/identity/bare_test.go
+++ b/identity/bare_test.go
@@ -18,7 +18,6 @@ func TestBare_Id(t *testing.T) {
func TestBareSerialize(t *testing.T) {
before := &Bare{
- login: "login",
email: "email",
name: "name",
avatarUrl: "avatar",
diff --git a/identity/common.go b/identity/common.go
index 007e10d6..0fd2b274 100644
--- a/identity/common.go
+++ b/identity/common.go
@@ -37,7 +37,7 @@ func UnmarshalJSON(raw json.RawMessage) (Interface, error) {
b := &Bare{}
err = json.Unmarshal(raw, b)
- if err == nil && (b.name != "" || b.login != "") {
+ if err == nil && b.name != "" {
return b, nil
}
diff --git a/identity/identity.go b/identity/identity.go
index cd47c1b7..c33a8818 100644
--- a/identity/identity.go
+++ b/identity/identity.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"os"
+ "reflect"
"strings"
"time"
@@ -55,14 +56,13 @@ func NewIdentity(name string, email string) *Identity {
}
}
-func NewIdentityFull(name string, email string, login string, avatarUrl string) *Identity {
+func NewIdentityFull(name string, email string, avatarUrl string) *Identity {
return &Identity{
id: entity.UnsetId,
versions: []*Version{
{
name: name,
email: email,
- login: login,
avatarURL: avatarUrl,
nonce: makeNonce(20),
},
@@ -271,8 +271,31 @@ func IsUserIdentitySet(repo repository.Repo) (bool, error) {
return len(configs) == 1, nil
}
-func (i *Identity) AddVersion(version *Version) {
- i.versions = append(i.versions, version)
+type Mutator struct {
+ Name string
+ Email string
+ AvatarUrl string
+ Keys []*Key
+}
+
+// Mutate allow to create a new version of the Identity
+func (i *Identity) Mutate(f func(orig Mutator) Mutator) {
+ orig := Mutator{
+ Name: i.Name(),
+ Email: i.Email(),
+ AvatarUrl: i.AvatarUrl(),
+ Keys: i.Keys(),
+ }
+ mutated := f(orig)
+ if reflect.DeepEqual(orig, mutated) {
+ return
+ }
+ i.versions = append(i.versions, &Version{
+ name: mutated.Name,
+ email: mutated.Email,
+ avatarURL: mutated.AvatarUrl,
+ keys: mutated.Keys,
+ })
}
// Write the identity into the Repository. In particular, this ensure that
@@ -478,24 +501,19 @@ func (i *Identity) Email() string {
return i.lastVersion().email
}
-// Login return the last version of the login
-func (i *Identity) Login() string {
- return i.lastVersion().login
-}
-
// AvatarUrl return the last version of the Avatar URL
func (i *Identity) AvatarUrl() string {
return i.lastVersion().avatarURL
}
// Keys return the last version of the valid keys
-func (i *Identity) Keys() []Key {
+func (i *Identity) Keys() []*Key {
return i.lastVersion().keys
}
// ValidKeysAtTime return the set of keys valid at a given lamport time
-func (i *Identity) ValidKeysAtTime(time lamport.Time) []Key {
- var result []Key
+func (i *Identity) ValidKeysAtTime(time lamport.Time) []*Key {
+ var result []*Key
for _, v := range i.versions {
if v.time > time {
@@ -511,16 +529,7 @@ func (i *Identity) ValidKeysAtTime(time lamport.Time) []Key {
// DisplayName return a non-empty string to display, representing the
// identity, based on the non-empty values.
func (i *Identity) 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")
+ return i.Name()
}
// IsProtected return true if the chain of git commits started to be signed.
@@ -540,9 +549,13 @@ func (i *Identity) LastModification() timestamp.Timestamp {
return timestamp.Timestamp(i.lastVersion().unixTime)
}
-// SetMetadata store arbitrary metadata along the last defined Version.
-// If the Version has been commit to git already, it won't be overwritten.
+// SetMetadata store arbitrary metadata along the last not-commit Version.
+// If the Version has been commit to git already, a new identical version is added and will need to be
+// commit.
func (i *Identity) SetMetadata(key string, value string) {
+ if i.lastVersion().commitHash != "" {
+ i.versions = append(i.versions, i.lastVersion().Clone())
+ }
i.lastVersion().SetMetadata(key, value)
}
@@ -575,3 +588,9 @@ func (i *Identity) MutableMetadata() map[string]string {
return metadata
}
+
+// addVersionForTest add a new version to the identity
+// Only for testing !
+func (i *Identity) addVersionForTest(version *Version) {
+ i.versions = append(i.versions, version)
+}
diff --git a/identity/identity_actions_test.go b/identity/identity_actions_test.go
index 142ffaa6..713b3246 100644
--- a/identity/identity_actions_test.go
+++ b/identity/identity_actions_test.go
@@ -48,14 +48,14 @@ func TestPushPull(t *testing.T) {
// Update both
- identity1.AddVersion(&Version{
+ identity1.addVersionForTest(&Version{
name: "name1b",
email: "email1b",
})
err = identity1.Commit(repoA)
require.NoError(t, err)
- identity2.AddVersion(&Version{
+ identity2.addVersionForTest(&Version{
name: "name2b",
email: "email2b",
})
@@ -92,7 +92,7 @@ func TestPushPull(t *testing.T) {
// Concurrent update
- identity1.AddVersion(&Version{
+ identity1.addVersionForTest(&Version{
name: "name1c",
email: "email1c",
})
@@ -102,7 +102,7 @@ func TestPushPull(t *testing.T) {
identity1B, err := ReadLocal(repoB, identity1.Id())
require.NoError(t, err)
- identity1B.AddVersion(&Version{
+ identity1B.addVersionForTest(&Version{
name: "name1concurrent",
email: "email1concurrent",
})
diff --git a/identity/identity_stub.go b/identity/identity_stub.go
index be52ffc0..7e2fcd94 100644
--- a/identity/identity_stub.go
+++ b/identity/identity_stub.go
@@ -64,11 +64,11 @@ func (IdentityStub) AvatarUrl() string {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
-func (IdentityStub) Keys() []Key {
+func (IdentityStub) Keys() []*Key {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
-func (IdentityStub) ValidKeysAtTime(time lamport.Time) []Key {
+func (IdentityStub) ValidKeysAtTime(_ lamport.Time) []*Key {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
diff --git a/identity/identity_test.go b/identity/identity_test.go
index f91c548f..ee6ccdf7 100644
--- a/identity/identity_test.go
+++ b/identity/identity_test.go
@@ -44,7 +44,7 @@ func TestIdentityCommitLoad(t *testing.T) {
time: 100,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyA"},
},
},
@@ -52,7 +52,7 @@ func TestIdentityCommitLoad(t *testing.T) {
time: 200,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyB"},
},
},
@@ -60,7 +60,7 @@ func TestIdentityCommitLoad(t *testing.T) {
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyC"},
},
},
@@ -79,20 +79,25 @@ func TestIdentityCommitLoad(t *testing.T) {
// add more version
- identity.AddVersion(&Version{
+ identity.Mutate(func(orig Mutator) Mutator {
+
+ return orig
+ })
+
+ identity.addVersionForTest(&Version{
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyD"},
},
})
- identity.AddVersion(&Version{
+ identity.addVersionForTest(&Version{
time: 300,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyE"},
},
})
@@ -123,7 +128,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 100,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyA"},
},
},
@@ -131,7 +136,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 200,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyB"},
},
},
@@ -139,7 +144,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyC"},
},
},
@@ -147,7 +152,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyD"},
},
},
@@ -155,7 +160,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 300,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyE"},
},
},
@@ -163,13 +168,13 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
}
assert.Nil(t, identity.ValidKeysAtTime(10))
- assert.Equal(t, identity.ValidKeysAtTime(100), []Key{{PubKey: "pubkeyA"}})
- assert.Equal(t, identity.ValidKeysAtTime(140), []Key{{PubKey: "pubkeyA"}})
- assert.Equal(t, identity.ValidKeysAtTime(200), []Key{{PubKey: "pubkeyB"}})
- assert.Equal(t, identity.ValidKeysAtTime(201), []Key{{PubKey: "pubkeyD"}})
- assert.Equal(t, identity.ValidKeysAtTime(202), []Key{{PubKey: "pubkeyD"}})
- assert.Equal(t, identity.ValidKeysAtTime(300), []Key{{PubKey: "pubkeyE"}})
- assert.Equal(t, identity.ValidKeysAtTime(3000), []Key{{PubKey: "pubkeyE"}})
+ assert.Equal(t, identity.ValidKeysAtTime(100), []*Key{{PubKey: "pubkeyA"}})
+ assert.Equal(t, identity.ValidKeysAtTime(140), []*Key{{PubKey: "pubkeyA"}})
+ assert.Equal(t, identity.ValidKeysAtTime(200), []*Key{{PubKey: "pubkeyB"}})
+ assert.Equal(t, identity.ValidKeysAtTime(201), []*Key{{PubKey: "pubkeyD"}})
+ assert.Equal(t, identity.ValidKeysAtTime(202), []*Key{{PubKey: "pubkeyD"}})
+ assert.Equal(t, identity.ValidKeysAtTime(300), []*Key{{PubKey: "pubkeyE"}})
+ assert.Equal(t, identity.ValidKeysAtTime(3000), []*Key{{PubKey: "pubkeyE"}})
}
// Test the immutable or mutable metadata search
@@ -189,7 +194,7 @@ func TestMetadata(t *testing.T) {
assertHasKeyValue(t, identity.MutableMetadata(), "key1", "value1")
// try override
- identity.AddVersion(&Version{
+ identity.addVersionForTest(&Version{
name: "René Descartes",
email: "rene.descartes@example.com",
})
diff --git a/identity/interface.go b/identity/interface.go
index 54a9da78..d138362d 100644
--- a/identity/interface.go
+++ b/identity/interface.go
@@ -17,17 +17,14 @@ type Interface interface {
// Email return the last version of the email
Email() string
- // Login return the last version of the login
- Login() string
-
// AvatarUrl return the last version of the Avatar URL
AvatarUrl() string
// Keys return the last version of the valid keys
- Keys() []Key
+ Keys() []*Key
// ValidKeysAtTime return the set of keys valid at a given lamport time
- ValidKeysAtTime(time lamport.Time) []Key
+ ValidKeysAtTime(time lamport.Time) []*Key
// DisplayName return a non-empty string to display, representing the
// identity, based on the non-empty values.
diff --git a/identity/key.go b/identity/key.go
index 90edfb60..cc948394 100644
--- a/identity/key.go
+++ b/identity/key.go
@@ -11,3 +11,8 @@ func (k *Key) Validate() error {
return nil
}
+
+func (k *Key) Clone() *Key {
+ clone := *k
+ return &clone
+}
diff --git a/identity/version.go b/identity/version.go
index 95530767..f9c7b262 100644
--- a/identity/version.go
+++ b/identity/version.go
@@ -24,14 +24,13 @@ type Version struct {
unixTime int64
name string
- email string
- login string
+ email string // as defined in git, not for bridges
avatarURL string
// The set of keys valid at that time, from this version onward, until they get removed
// in a new version. This allow to have multiple key for the same identity (e.g. one per
// device) as well as revoke key.
- keys []Key
+ keys []*Key
// This optional array is here to ensure a better randomness of the identity id to avoid collisions.
// It has no functional purpose and should be ignored.
@@ -53,13 +52,28 @@ type VersionJSON struct {
UnixTime int64 `json:"unix_time"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
- Login string `json:"login,omitempty"`
AvatarUrl string `json:"avatar_url,omitempty"`
- Keys []Key `json:"pub_keys,omitempty"`
+ Keys []*Key `json:"pub_keys,omitempty"`
Nonce []byte `json:"nonce,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
+// Make a deep copy
+func (v *Version) Clone() *Version {
+ clone := &Version{
+ name: v.name,
+ email: v.email,
+ avatarURL: v.avatarURL,
+ keys: make([]*Key, len(v.keys)),
+ }
+
+ for i, key := range v.keys {
+ clone.keys[i] = key.Clone()
+ }
+
+ return clone
+}
+
func (v *Version) MarshalJSON() ([]byte, error) {
return json.Marshal(VersionJSON{
FormatVersion: formatVersion,
@@ -67,7 +81,6 @@ func (v *Version) MarshalJSON() ([]byte, error) {
UnixTime: v.unixTime,
Name: v.name,
Email: v.email,
- Login: v.login,
AvatarUrl: v.avatarURL,
Keys: v.keys,
Nonce: v.nonce,
@@ -90,7 +103,6 @@ func (v *Version) UnmarshalJSON(data []byte) error {
v.unixTime = aux.UnixTime
v.name = aux.Name
v.email = aux.Email
- v.login = aux.Login
v.avatarURL = aux.AvatarUrl
v.keys = aux.Keys
v.nonce = aux.Nonce
@@ -108,8 +120,8 @@ func (v *Version) Validate() error {
return fmt.Errorf("lamport time not set")
}
- if text.Empty(v.name) && text.Empty(v.login) {
- return fmt.Errorf("either name or login should be set")
+ if text.Empty(v.name) {
+ return fmt.Errorf("name not set")
}
if strings.Contains(v.name, "\n") {
@@ -120,14 +132,6 @@ func (v *Version) Validate() error {
return fmt.Errorf("name is not fully printable")
}
- if strings.Contains(v.login, "\n") {
- return fmt.Errorf("login should be a single line")
- }
-
- if !text.Safe(v.login) {
- return fmt.Errorf("login is not fully printable")
- }
-
if strings.Contains(v.email, "\n") {
return fmt.Errorf("email should be a single line")
}
@@ -202,7 +206,7 @@ func (v *Version) GetMetadata(key string) (string, bool) {
return val, ok
}
-// AllMetadata return all metadata for this Identity
+// AllMetadata return all metadata for this Version
func (v *Version) AllMetadata() map[string]string {
return v.metadata
}
diff --git a/identity/version_test.go b/identity/version_test.go
index 8c4c8d99..25848eb5 100644
--- a/identity/version_test.go
+++ b/identity/version_test.go
@@ -9,11 +9,10 @@ import (
func TestVersionSerialize(t *testing.T) {
before := &Version{
- login: "login",
name: "name",
email: "email",
avatarURL: "avatarUrl",
- keys: []Key{
+ keys: []*Key{
{
Fingerprint: "fingerprint1",
PubKey: "pubkey1",