diff options
author | Michael Muré <batolettre@gmail.com> | 2020-02-09 01:31:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-09 01:31:00 +0100 |
commit | 9e1a987b4d94dc5c2115423ede5954d4faf1d342 (patch) | |
tree | e30bb28d55444a7d1e66c8fa8b8ba7d413805473 /identity | |
parent | 97bc5ccd229b7b438262a84e3c42783b4d4a82af (diff) | |
parent | 9b1aaa032d36e1ac05504916e359f767d1622d9d (diff) | |
download | git-bug-9e1a987b4d94dc5c2115423ede5954d4faf1d342.tar.gz |
Merge pull request #294 from MichaelMure/cred-metadata
Cred metadata
Diffstat (limited to 'identity')
-rw-r--r-- | identity/bare.go | 45 | ||||
-rw-r--r-- | identity/bare_test.go | 1 | ||||
-rw-r--r-- | identity/common.go | 2 | ||||
-rw-r--r-- | identity/identity.go | 67 | ||||
-rw-r--r-- | identity/identity_actions_test.go | 8 | ||||
-rw-r--r-- | identity/identity_stub.go | 4 | ||||
-rw-r--r-- | identity/identity_test.go | 45 | ||||
-rw-r--r-- | identity/interface.go | 7 | ||||
-rw-r--r-- | identity/key.go | 5 | ||||
-rw-r--r-- | identity/version.go | 40 | ||||
-rw-r--r-- | identity/version_test.go | 3 |
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", |