Documentation ¶
Overview ¶
Package identity contains the identity data model and low-level related functions
Index ¶
- Constants
- Variables
- func AddKeyMutator(key *Key) func(mutator Mutator) Mutator
- func DecodeKeyFingerprint(keyFingerprint string) ([20]byte, error)
- func EncodeKeyFingerprint(fingerprint [20]byte) string
- func GetUserIdentityId(repo repository.Repo) (entity.Id, error)
- func IsUserIdentitySet(repo repository.Repo) (bool, error)
- func MergeAll(repo repository.ClockedRepo, remote string) <-chan entity.MergeResult
- func NewErrMultipleMatch(matching []entity.Id) *entity.ErrMultipleMatch
- func ReadAllLocalIdentities(repo repository.ClockedRepo) <-chan StreamedIdentity
- func ReadAllRemoteIdentities(repo repository.ClockedRepo, remote string) <-chan StreamedIdentity
- func RemoveKeyMutator(fingerprint string, removedKey **Key) func(mutator Mutator) Mutator
- func SetUserIdentity(repo repository.RepoConfig, identity *Identity) error
- type Bare
- func (i *Bare) AvatarUrl() string
- func (i *Bare) Commit(repo repository.ClockedRepo) error
- func (i *Bare) CommitAsNeeded(repo repository.ClockedRepo) error
- func (i *Bare) DisplayName() string
- func (i *Bare) Email() string
- func (i *Bare) Id() entity.Id
- func (i *Bare) IsProtected() bool
- func (i *Bare) Keys() []*Key
- func (i *Bare) LastModification() timestamp.Timestamp
- func (i *Bare) LastModificationLamport() lamport.Time
- func (i *Bare) Login() string
- func (i *Bare) MarshalJSON() ([]byte, error)
- func (i *Bare) Name() string
- func (i *Bare) PhabID() string
- func (i *Bare) UnmarshalJSON(data []byte) error
- func (i *Bare) ValidKeysAtTime(_ lamport.Time) []*Key
- func (i *Bare) Validate() error
- type Identity
- func GetUserIdentity(repo repository.ClockedRepo) (*Identity, error)
- func NewFromGitUser(repo repository.Repo) (*Identity, error)
- func NewIdentity(name string, email string) *Identity
- func NewIdentityFull(name string, email string, login string, avatarUrl string, phabID string, ...) *Identity
- func ReadCommit(repo repository.Repo, hash repository.Hash) (*Identity, error)
- func ReadLocal(repo repository.ClockedRepo, id entity.Id) (*Identity, error)
- func ReadRemote(repo repository.ClockedRepo, remote string, id string) (*Identity, error)
- func (i *Identity) AvatarUrl() string
- func (i *Identity) Commit(repo repository.ClockedRepo) error
- func (i *Identity) CommitAsNeeded(repo repository.ClockedRepo) error
- func (i *Identity) DisplayName() string
- func (i *Identity) Email() string
- func (i *Identity) GiteaID() int64
- func (i *Identity) Id() entity.Id
- func (i *Identity) ImmutableMetadata() map[string]string
- func (i *Identity) IsProtected() bool
- func (i *Identity) Keys() []*Key
- func (i *Identity) LastModification() timestamp.Timestamp
- func (i *Identity) LastModificationLamport() lamport.Time
- func (i *Identity) Login() string
- func (i *Identity) MarshalJSON() ([]byte, error)
- func (i *Identity) Merge(repo repository.Repo, other *Identity) (bool, error)
- func (i *Identity) MutableMetadata() map[string]string
- func (i *Identity) Mutate(f func(orig Mutator) Mutator)
- func (i *Identity) Name() string
- func (i *Identity) NeedCommit() bool
- func (i *Identity) PhabID() string
- func (i *Identity) SetMetadata(key string, value string)
- func (i *Identity) UnmarshalJSON(data []byte) error
- func (i *Identity) ValidKeysAtTime(time lamport.Time) []*Key
- func (i *Identity) Validate() error
- func (i *Identity) Versions() []*Version
- type IdentityStub
- func (IdentityStub) AvatarUrl() string
- func (IdentityStub) Commit(repo repository.ClockedRepo) error
- func (i *IdentityStub) CommitAsNeeded(repo repository.ClockedRepo) error
- func (IdentityStub) DisplayName() string
- func (IdentityStub) Email() string
- func (IdentityStub) GiteaID() string
- func (i *IdentityStub) Id() entity.Id
- func (IdentityStub) IsProtected() bool
- func (IdentityStub) Keys() []*Key
- func (i *IdentityStub) LastModification() timestamp.Timestamp
- func (i *IdentityStub) LastModificationLamport() lamport.Time
- func (IdentityStub) Login() string
- func (i *IdentityStub) MarshalJSON() ([]byte, error)
- func (IdentityStub) Name() string
- func (IdentityStub) PhabID() string
- func (i *IdentityStub) UnmarshalJSON(data []byte) error
- func (IdentityStub) ValidKeysAtTime(_ lamport.Time) []*Key
- func (IdentityStub) Validate() error
- type Interface
- type Key
- type Mutator
- type Resolver
- type SimpleResolver
- type StreamedIdentity
- type Version
- func (v *Version) AllMetadata() map[string]string
- func (v *Version) Clone() *Version
- func (v *Version) CommitHash() repository.Hash
- func (v *Version) GetMetadata(key string) (string, bool)
- func (v *Version) Keys() []*Key
- func (v *Version) MarshalJSON() ([]byte, error)
- func (v *Version) SetMetadata(key string, value string)
- func (v *Version) Time() lamport.Time
- func (v *Version) UnmarshalJSON(data []byte) error
- func (v *Version) Validate() error
- func (v *Version) Write(repo repository.Repo) (repository.Hash, error)
- type VersionJSON
Constants ¶
const Namespace = "identities"
Variables ¶
var ClockLoader = repository.ClockLoader{ Clocks: []string{identityEditClockName}, Witnesser: func(repo repository.ClockedRepo) error { editClock, err := repo.GetOrCreateClock(identityEditClockName) if err != nil { return err } for id := range ReadAllLocalIdentities(repo) { if id.Err != nil { return id.Err } for _, ver := range id.Identity.versions { err = editClock.Witness(ver.time) if err != nil { return err } } } return nil }, }
ClockLoader is the repository.ClockLoader for the Identity entity
var ErrIdentityNotExist = errors.New("identity doesn't exist")
var ErrMultipleIdentitiesSet = errors.New("multiple user identities set")
var ErrNoIdentitySet = errors.New("No identity is set.\n" +
"To interact with bugs, an identity first needs to be created using " +
"\"git bug user create\"")
var ErrNonFastForwardMerge = errors.New("non fast-forward identity merge")
Functions ¶
func AddKeyMutator ¶
func DecodeKeyFingerprint ¶
DecodeKeyFingerprint decodes a 40 hex digits long fingerprint into bytes.
func EncodeKeyFingerprint ¶
func GetUserIdentityId ¶
func GetUserIdentityId(repo repository.Repo) (entity.Id, error)
func IsUserIdentitySet ¶
func IsUserIdentitySet(repo repository.Repo) (bool, error)
IsUserIdentitySet say if the user has set his identity
func MergeAll ¶
func MergeAll(repo repository.ClockedRepo, remote string) <-chan entity.MergeResult
MergeAll will merge all the available remote identity
func NewErrMultipleMatch ¶
func NewErrMultipleMatch(matching []entity.Id) *entity.ErrMultipleMatch
func ReadAllLocalIdentities ¶
func ReadAllLocalIdentities(repo repository.ClockedRepo) <-chan StreamedIdentity
ReadAllLocalIdentities read and parse all local Identity
func ReadAllRemoteIdentities ¶
func ReadAllRemoteIdentities(repo repository.ClockedRepo, remote string) <-chan StreamedIdentity
ReadAllRemoteIdentities read and parse all remote Identity for a given remote
func RemoveKeyMutator ¶
func SetUserIdentity ¶
func SetUserIdentity(repo repository.RepoConfig, identity *Identity) error
SetUserIdentity store the user identity's id in the git config
Types ¶
type Bare ¶
type Bare struct {
// contains filtered or unexported fields
}
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. Deprecated: legacy identity for compat, might make sense to ditch entirely for simplicity but that would be a breaking change.
func NewBareFull ¶
func (*Bare) Commit ¶
func (i *Bare) Commit(repo repository.ClockedRepo) error
Write the identity into the Repository. In particular, this ensure that the Id is properly set.
func (*Bare) CommitAsNeeded ¶
func (i *Bare) CommitAsNeeded(repo repository.ClockedRepo) error
If needed, write the identity into the Repository. In particular, this ensure that the Id is properly set.
func (*Bare) DisplayName ¶
DisplayName return a non-empty string to display, representing the identity, based on the non-empty values.
func (*Bare) IsProtected ¶
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 (*Bare) LastModification ¶
LastModification return the timestamp at which the last version of the identity became valid.
func (*Bare) LastModificationLamport ¶
LastModificationLamportTime return the Lamport time at which the last version of the identity became valid.
func (*Bare) MarshalJSON ¶
func (*Bare) UnmarshalJSON ¶
func (*Bare) ValidKeysAtTime ¶
ValidKeysAtTime return the set of keys valid at a given lamport time
type Identity ¶
type Identity struct {
// contains filtered or unexported fields
}
func GetUserIdentity ¶
func GetUserIdentity(repo repository.ClockedRepo) (*Identity, error)
GetUserIdentity read the current user identity, set with a git config entry
func NewFromGitUser ¶
func NewFromGitUser(repo repository.Repo) (*Identity, error)
NewFromGitUser will query the repository for user detail and build the corresponding Identity
func NewIdentity ¶
func NewIdentityFull ¶
func ReadCommit ¶
func ReadCommit(repo repository.Repo, hash repository.Hash) (*Identity, error)
ReadCommit loads an identity data from a single commit in git
func ReadLocal ¶
func ReadLocal(repo repository.ClockedRepo, id entity.Id) (*Identity, error)
ReadLocal load a local Identity from the identities data available in git
func ReadRemote ¶
func ReadRemote(repo repository.ClockedRepo, remote string, id string) (*Identity, error)
ReadRemote load a remote Identity from the identities data available in git
func (*Identity) Commit ¶
func (i *Identity) Commit(repo repository.ClockedRepo) error
Write the identity into the Repository. In particular, this ensure that the Id is properly set.
func (*Identity) CommitAsNeeded ¶
func (i *Identity) CommitAsNeeded(repo repository.ClockedRepo) error
func (*Identity) DisplayName ¶
DisplayName return a non-empty string to display, representing the identity, based on the non-empty values.
func (*Identity) ImmutableMetadata ¶
ImmutableMetadata return all metadata for this Identity, accumulated from each Version. If multiple value are found, the first defined takes precedence.
func (*Identity) IsProtected ¶
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 (*Identity) LastModification ¶
LastModification return the timestamp at which the last version of the identity became valid.
func (*Identity) LastModificationLamport ¶
LastModificationLamportTime return the Lamport time at which the last version of the identity became valid.
func (*Identity) MarshalJSON ¶
MarshalJSON will only serialize the id
func (*Identity) Merge ¶
Merge will merge a different version of the same Identity
To make sure that an Identity history can't be altered, a strict fast-forward only policy is applied here. As an Identity should be tied to a single user, this should work in practice but it does leave a possibility that a user would edit his Identity from two different repo concurrently and push the changes in a non-centralized network of repositories. In this case, it would result in some of the repo accepting one version and some other accepting another, preventing the network in general to converge to the same result. This would create a sort of partition of the network, and manual cleaning would be required.
An alternative approach would be to have a determinist rebase:
- any commits present in both local and remote version would be kept, never changed.
- newer commits would be merged in a linear chain of commits, ordered based on the Lamport time
However, this approach leave the possibility, in the case of a compromised crypto keys, of forging a new version with a bogus Lamport time to be inserted before a legit version, invalidating the correct version and hijacking the Identity. There would only be a short period of time where this would be possible (before the network converge) but I'm not confident enough to implement that. I choose the strict fast-forward only approach, despite it's potential problem with two different version as mentioned above.
func (*Identity) MutableMetadata ¶
MutableMetadata return all metadata for this Identity, accumulated from each Version. If multiple value are found, the last defined takes precedence.
func (*Identity) NeedCommit ¶
func (*Identity) SetMetadata ¶
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 (*Identity) UnmarshalJSON ¶
UnmarshalJSON will only read the id Users of this package are expected to run Load() to load the remaining data from the identities data in git.
func (*Identity) ValidKeysAtTime ¶
ValidKeysAtTime return the set of keys valid at a given lamport time
type IdentityStub ¶
type IdentityStub struct {
// contains filtered or unexported fields
}
IdentityStub is an almost empty Identity, holding only the id. When a normal Identity is serialized into JSON, only the id is serialized. All the other data are stored in git in a chain of commit + a ref. When this JSON is deserialized, an IdentityStub is returned instead, to be replaced later by the proper Identity, loaded from the Repo.
func (IdentityStub) AvatarUrl ¶
func (IdentityStub) AvatarUrl() string
func (IdentityStub) Commit ¶
func (IdentityStub) Commit(repo repository.ClockedRepo) error
func (*IdentityStub) CommitAsNeeded ¶
func (i *IdentityStub) CommitAsNeeded(repo repository.ClockedRepo) error
func (IdentityStub) DisplayName ¶
func (IdentityStub) DisplayName() string
func (IdentityStub) Email ¶
func (IdentityStub) Email() string
func (IdentityStub) GiteaID ¶
func (IdentityStub) GiteaID() string
func (IdentityStub) IsProtected ¶
func (IdentityStub) IsProtected() bool
func (IdentityStub) Keys ¶
func (IdentityStub) Keys() []*Key
func (*IdentityStub) LastModification ¶
func (i *IdentityStub) LastModification() timestamp.Timestamp
func (*IdentityStub) LastModificationLamport ¶
func (i *IdentityStub) LastModificationLamport() lamport.Time
func (IdentityStub) Login ¶
func (IdentityStub) Login() string
func (*IdentityStub) MarshalJSON ¶
func (i *IdentityStub) MarshalJSON() ([]byte, error)
func (IdentityStub) Name ¶
func (IdentityStub) Name() string
func (IdentityStub) PhabID ¶
func (IdentityStub) PhabID() string
func (*IdentityStub) UnmarshalJSON ¶
func (i *IdentityStub) UnmarshalJSON(data []byte) error
func (IdentityStub) ValidKeysAtTime ¶
func (IdentityStub) ValidKeysAtTime(_ lamport.Time) []*Key
func (IdentityStub) Validate ¶
func (IdentityStub) Validate() error
type Interface ¶
type Interface interface { // Id return the Identity identifier Id() entity.Id // Name return the last version of the name // Can be empty. Name() string // Email return the last version of the email // Can be empty. Email() string // Login return the last version of the login // Can be empty. // Warning: this login can be defined when importing from a bridge but should *not* be // used to identify an identity as multiple bridge with different login can map to the same // identity. Use the metadata system for that usage instead. Login() string // AvatarUrl return the last version of the Avatar URL // Can be empty. AvatarUrl() string // PhabID return the last version of the Phabricator ID // Can be empty. PhabID() string // Keys return the last version of the valid keys // Can be empty. Keys() []*Key // ValidKeysAtTime return the set of keys valid at a given lamport time // Can be empty. ValidKeysAtTime(time lamport.Time) []*Key // DisplayName return a non-empty string to display, representing the // identity, based on the non-empty values. DisplayName() string // Validate check if the Identity data is valid Validate() error // Write the identity into the Repository. In particular, this ensure that // the Id is properly set. Commit(repo repository.ClockedRepo) error // If needed, write the identity into the Repository. In particular, this // ensure that the Id is properly set. CommitAsNeeded(repo repository.ClockedRepo) error // 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. IsProtected() bool // LastModificationLamportTime return the Lamport time at which the last version of the identity became valid. LastModificationLamport() lamport.Time // LastModification return the timestamp at which the last version of the identity became valid. LastModification() timestamp.Timestamp }
func UnmarshalJSON ¶
func UnmarshalJSON(raw json.RawMessage) (Interface, error)
Custom unmarshaling function to allow package user to delegate the decoding of an Identity and distinguish between an Identity and a Bare.
If the given message has a "id" field, it's considered being a proper Identity.
type Key ¶
type Key struct {
// contains filtered or unexported fields
}
Key hold a cryptographic public key
func NewKeyFromArmored ¶
func (Key) CreationTime ¶
func (Key) Fingerprint ¶
func (*Key) MarshalJSON ¶
func (*Key) UnmarshalJSON ¶
type Resolver ¶
Resolver define the interface of an Identity resolver, able to load an identity from, for example, a repo or a cache.
type SimpleResolver ¶
type SimpleResolver struct {
// contains filtered or unexported fields
}
DefaultResolver is a Resolver loading Identities directly from a Repo
func NewSimpleResolver ¶
func NewSimpleResolver(repo repository.ClockedRepo) *SimpleResolver
func (*SimpleResolver) ResolveIdentity ¶
func (r *SimpleResolver) ResolveIdentity(id entity.Id) (Interface, error)
type StreamedIdentity ¶
type Version ¶
type Version struct {
// contains filtered or unexported fields
}
Version is a complete set of information about an Identity at a point in time.
func (*Version) AllMetadata ¶
AllMetadata return all metadata for this Version
func (*Version) CommitHash ¶
func (v *Version) CommitHash() repository.Hash
func (*Version) GetMetadata ¶
GetMetadata retrieve arbitrary metadata about the Version
func (*Version) MarshalJSON ¶
func (*Version) SetMetadata ¶
SetMetadata store arbitrary metadata about a version or an Identity in general If the Version has been commit to git already, it won't be overwritten.
func (*Version) UnmarshalJSON ¶
func (*Version) Write ¶
func (v *Version) Write(repo repository.Repo) (repository.Hash, error)
Write will serialize and store the Version as a git blob and return its hash
type VersionJSON ¶
type VersionJSON struct { // Additional field to version the data FormatVersion uint `json:"version"` Time lamport.Time `json:"time"` 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"` PhabID string `json:"phab_id,omitempty"` GiteaID int64 `json:"gitea_id,omitempty"` Keys []*Key `json:"pub_keys,omitempty"` Nonce []byte `json:"nonce,omitempty"` Metadata map[string]string `json:"metadata,omitempty"` }