aboutsummaryrefslogtreecommitdiffstats
path: root/bridge/core
diff options
context:
space:
mode:
Diffstat (limited to 'bridge/core')
-rw-r--r--bridge/core/auth/credential.go232
-rw-r--r--bridge/core/auth/credential_test.go109
-rw-r--r--bridge/core/auth/options.go62
-rw-r--r--bridge/core/auth/token.go95
-rw-r--r--bridge/core/bridge.go32
-rw-r--r--bridge/core/interfaces.go7
-rw-r--r--bridge/core/token.go296
7 files changed, 512 insertions, 321 deletions
diff --git a/bridge/core/auth/credential.go b/bridge/core/auth/credential.go
new file mode 100644
index 00000000..a462a116
--- /dev/null
+++ b/bridge/core/auth/credential.go
@@ -0,0 +1,232 @@
+package auth
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "strings"
+ "time"
+
+ "github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/repository"
+)
+
+const (
+ configKeyPrefix = "git-bug.auth"
+ configKeyKind = "kind"
+ configKeyUserId = "userid"
+ configKeyTarget = "target"
+ configKeyCreateTime = "createtime"
+)
+
+type CredentialKind string
+
+const (
+ KindToken CredentialKind = "token"
+ KindLoginPassword CredentialKind = "login-password"
+)
+
+var ErrCredentialNotExist = errors.New("credential doesn't exist")
+
+func NewErrMultipleMatchCredential(matching []entity.Id) *entity.ErrMultipleMatch {
+ return entity.NewErrMultipleMatch("credential", matching)
+}
+
+type Credential interface {
+ ID() entity.Id
+ UserId() entity.Id
+ Target() string
+ Kind() CredentialKind
+ CreateTime() time.Time
+ Validate() error
+
+ // Return all the specific properties of the credential that need to be saved into the configuration.
+ // This does not include Target, User, Kind and CreateTime.
+ ToConfig() map[string]string
+}
+
+// Load loads a credential from the repo config
+func LoadWithId(repo repository.RepoConfig, id entity.Id) (Credential, error) {
+ keyPrefix := fmt.Sprintf("%s.%s.", configKeyPrefix, id)
+
+ // read token config pairs
+ rawconfigs, err := repo.GlobalConfig().ReadAll(keyPrefix)
+ if err != nil {
+ // Not exactly right due to the limitation of ReadAll()
+ return nil, ErrCredentialNotExist
+ }
+
+ return loadFromConfig(rawconfigs, id)
+}
+
+// LoadWithPrefix load a credential from the repo config with a prefix
+func LoadWithPrefix(repo repository.RepoConfig, prefix string) (Credential, error) {
+ creds, err := List(repo)
+ if err != nil {
+ return nil, err
+ }
+
+ // preallocate but empty
+ matching := make([]Credential, 0, 5)
+
+ for _, cred := range creds {
+ if cred.ID().HasPrefix(prefix) {
+ matching = append(matching, cred)
+ }
+ }
+
+ if len(matching) > 1 {
+ ids := make([]entity.Id, len(matching))
+ for i, cred := range matching {
+ ids[i] = cred.ID()
+ }
+ return nil, NewErrMultipleMatchCredential(ids)
+ }
+
+ if len(matching) == 0 {
+ return nil, ErrCredentialNotExist
+ }
+
+ return matching[0], nil
+}
+
+func loadFromConfig(rawConfigs map[string]string, id entity.Id) (Credential, error) {
+ keyPrefix := fmt.Sprintf("%s.%s.", configKeyPrefix, id)
+
+ // trim key prefix
+ configs := make(map[string]string)
+ for key, value := range rawConfigs {
+ newKey := strings.TrimPrefix(key, keyPrefix)
+ configs[newKey] = value
+ }
+
+ var cred Credential
+
+ switch CredentialKind(configs[configKeyKind]) {
+ case KindToken:
+ cred = NewTokenFromConfig(configs)
+ case KindLoginPassword:
+ default:
+ return nil, fmt.Errorf("unknown credential type %s", configs[configKeyKind])
+ }
+
+ return cred, nil
+}
+
+// List load all existing credentials
+func List(repo repository.RepoConfig, opts ...Option) ([]Credential, error) {
+ rawConfigs, err := repo.GlobalConfig().ReadAll(configKeyPrefix + ".")
+ if err != nil {
+ return nil, err
+ }
+
+ re, err := regexp.Compile(configKeyPrefix + `.([^.]+).([^.]+)`)
+ if err != nil {
+ panic(err)
+ }
+
+ mapped := make(map[string]map[string]string)
+
+ for key, val := range rawConfigs {
+ res := re.FindStringSubmatch(key)
+ if res == nil {
+ continue
+ }
+ if mapped[res[1]] == nil {
+ mapped[res[1]] = make(map[string]string)
+ }
+ mapped[res[1]][res[2]] = val
+ }
+
+ matcher := matcher(opts)
+
+ var credentials []Credential
+ for id, kvs := range mapped {
+ cred, err := loadFromConfig(kvs, entity.Id(id))
+ if err != nil {
+ return nil, err
+ }
+ if matcher.Match(cred) {
+ credentials = append(credentials, cred)
+ }
+ }
+
+ return credentials, nil
+}
+
+// IdExist return whether a credential id exist or not
+func IdExist(repo repository.RepoConfig, id entity.Id) bool {
+ _, err := LoadWithId(repo, id)
+ return err == nil
+}
+
+// PrefixExist return whether a credential id prefix exist or not
+func PrefixExist(repo repository.RepoConfig, prefix string) bool {
+ _, err := LoadWithPrefix(repo, prefix)
+ return err == nil
+}
+
+// Store stores a credential in the global git config
+func Store(repo repository.RepoConfig, cred Credential) error {
+ confs := cred.ToConfig()
+
+ prefix := fmt.Sprintf("%s.%s.", configKeyPrefix, cred.ID())
+
+ // Kind
+ err := repo.GlobalConfig().StoreString(prefix+configKeyKind, string(cred.Kind()))
+ if err != nil {
+ return err
+ }
+
+ // UserId
+ err = repo.GlobalConfig().StoreString(prefix+configKeyUserId, cred.UserId().String())
+ if err != nil {
+ return err
+ }
+
+ // Target
+ err = repo.GlobalConfig().StoreString(prefix+configKeyTarget, cred.Target())
+ if err != nil {
+ return err
+ }
+
+ // CreateTime
+ err = repo.GlobalConfig().StoreTimestamp(prefix+configKeyCreateTime, cred.CreateTime())
+ if err != nil {
+ return err
+ }
+
+ // Custom
+ for key, val := range confs {
+ err := repo.GlobalConfig().StoreString(prefix+key, val)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// Remove removes a credential from the global git config
+func Remove(repo repository.RepoConfig, id entity.Id) error {
+ keyPrefix := fmt.Sprintf("%s.%s", configKeyPrefix, id)
+ return repo.GlobalConfig().RemoveAll(keyPrefix)
+}
+
+/*
+ * Sorting
+ */
+
+type ById []Credential
+
+func (b ById) Len() int {
+ return len(b)
+}
+
+func (b ById) Less(i, j int) bool {
+ return b[i].ID() < b[j].ID()
+}
+
+func (b ById) Swap(i, j int) {
+ b[i], b[j] = b[j], b[i]
+}
diff --git a/bridge/core/auth/credential_test.go b/bridge/core/auth/credential_test.go
new file mode 100644
index 00000000..f91d273d
--- /dev/null
+++ b/bridge/core/auth/credential_test.go
@@ -0,0 +1,109 @@
+package auth
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/identity"
+ "github.com/MichaelMure/git-bug/repository"
+)
+
+func TestCredential(t *testing.T) {
+ repo := repository.NewMockRepoForTest()
+
+ user1 := identity.NewIdentity("user1", "email")
+ err := user1.Commit(repo)
+ assert.NoError(t, err)
+
+ user2 := identity.NewIdentity("user2", "email")
+ err = user2.Commit(repo)
+ assert.NoError(t, err)
+
+ storeToken := func(user identity.Interface, val string, target string) *Token {
+ token := NewToken(user.Id(), val, target)
+ err = Store(repo, token)
+ require.NoError(t, err)
+ return token
+ }
+
+ token := storeToken(user1, "foobar", "github")
+
+ // Store + Load
+ err = Store(repo, token)
+ assert.NoError(t, err)
+
+ token2, err := LoadWithId(repo, token.ID())
+ assert.NoError(t, err)
+ assert.Equal(t, token.createTime.Unix(), token2.CreateTime().Unix())
+ token.createTime = token2.CreateTime()
+ assert.Equal(t, token, token2)
+
+ prefix := string(token.ID())[:10]
+
+ // LoadWithPrefix
+ token3, err := LoadWithPrefix(repo, prefix)
+ assert.NoError(t, err)
+ assert.Equal(t, token.createTime.Unix(), token3.CreateTime().Unix())
+ token.createTime = token3.CreateTime()
+ assert.Equal(t, token, token3)
+
+ token4 := storeToken(user1, "foo", "gitlab")
+ token5 := storeToken(user2, "bar", "github")
+
+ // List + options
+ creds, err := List(repo, WithTarget("github"))
+ assert.NoError(t, err)
+ sameIds(t, creds, []Credential{token, token5})
+
+ creds, err = List(repo, WithTarget("gitlab"))
+ assert.NoError(t, err)
+ sameIds(t, creds, []Credential{token4})
+
+ creds, err = List(repo, WithUser(user1))
+ assert.NoError(t, err)
+ sameIds(t, creds, []Credential{token, token4})
+
+ creds, err = List(repo, WithUserId(user1.Id()))
+ assert.NoError(t, err)
+ sameIds(t, creds, []Credential{token, token4})
+
+ creds, err = List(repo, WithKind(KindToken))
+ assert.NoError(t, err)
+ sameIds(t, creds, []Credential{token, token4, token5})
+
+ creds, err = List(repo, WithKind(KindLoginPassword))
+ assert.NoError(t, err)
+ sameIds(t, creds, []Credential{})
+
+ // Exist
+ exist := IdExist(repo, token.ID())
+ assert.True(t, exist)
+
+ exist = PrefixExist(repo, prefix)
+ assert.True(t, exist)
+
+ // Remove
+ err = Remove(repo, token.ID())
+ assert.NoError(t, err)
+
+ creds, err = List(repo)
+ assert.NoError(t, err)
+ sameIds(t, creds, []Credential{token4, token5})
+}
+
+func sameIds(t *testing.T, a []Credential, b []Credential) {
+ t.Helper()
+
+ ids := func(creds []Credential) []entity.Id {
+ result := make([]entity.Id, len(creds))
+ for i, cred := range creds {
+ result[i] = cred.ID()
+ }
+ return result
+ }
+
+ assert.ElementsMatch(t, ids(a), ids(b))
+}
diff --git a/bridge/core/auth/options.go b/bridge/core/auth/options.go
new file mode 100644
index 00000000..7bcda68e
--- /dev/null
+++ b/bridge/core/auth/options.go
@@ -0,0 +1,62 @@
+package auth
+
+import (
+ "github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/identity"
+)
+
+type options struct {
+ target string
+ userId entity.Id
+ kind CredentialKind
+}
+
+type Option func(opts *options)
+
+func matcher(opts []Option) *options {
+ result := &options{}
+ for _, opt := range opts {
+ opt(result)
+ }
+ return result
+}
+
+func (opts *options) Match(cred Credential) bool {
+ if opts.target != "" && cred.Target() != opts.target {
+ return false
+ }
+
+ if opts.userId != "" && cred.UserId() != opts.userId {
+ return false
+ }
+
+ if opts.kind != "" && cred.Kind() != opts.kind {
+ return false
+ }
+
+ return true
+}
+
+func WithTarget(target string) Option {
+ return func(opts *options) {
+ opts.target = target
+ }
+}
+
+func WithUser(user identity.Interface) Option {
+ return func(opts *options) {
+ opts.userId = user.Id()
+ }
+}
+
+func WithUserId(userId entity.Id) Option {
+ return func(opts *options) {
+ opts.userId = userId
+ }
+}
+
+func WithKind(kind CredentialKind) Option {
+ return func(opts *options) {
+ opts.kind = kind
+ }
+}
diff --git a/bridge/core/auth/token.go b/bridge/core/auth/token.go
new file mode 100644
index 00000000..12a3bfc0
--- /dev/null
+++ b/bridge/core/auth/token.go
@@ -0,0 +1,95 @@
+package auth
+
+import (
+ "crypto/sha256"
+ "fmt"
+ "time"
+
+ "github.com/MichaelMure/git-bug/bridge/core"
+ "github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/repository"
+)
+
+const (
+ tokenValueKey = "value"
+)
+
+var _ Credential = &Token{}
+
+// Token holds an API access token data
+type Token struct {
+ userId entity.Id
+ target string
+ createTime time.Time
+ Value string
+}
+
+// NewToken instantiate a new token
+func NewToken(userId entity.Id, value, target string) *Token {
+ return &Token{
+ userId: userId,
+ target: target,
+ createTime: time.Now(),
+ Value: value,
+ }
+}
+
+func NewTokenFromConfig(conf map[string]string) *Token {
+ token := &Token{}
+
+ token.userId = entity.Id(conf[configKeyUserId])
+ token.target = conf[configKeyTarget]
+ if createTime, ok := conf[configKeyCreateTime]; ok {
+ if t, err := repository.ParseTimestamp(createTime); err == nil {
+ token.createTime = t
+ }
+ }
+
+ token.Value = conf[tokenValueKey]
+
+ return token
+}
+
+func (t *Token) ID() entity.Id {
+ sum := sha256.Sum256([]byte(t.target + t.Value))
+ return entity.Id(fmt.Sprintf("%x", sum))
+}
+
+func (t *Token) UserId() entity.Id {
+ return t.userId
+}
+
+func (t *Token) Target() string {
+ return t.target
+}
+
+func (t *Token) Kind() CredentialKind {
+ return KindToken
+}
+
+func (t *Token) CreateTime() time.Time {
+ return t.createTime
+}
+
+// Validate ensure token important fields are valid
+func (t *Token) Validate() error {
+ if t.Value == "" {
+ return fmt.Errorf("missing value")
+ }
+ if t.target == "" {
+ return fmt.Errorf("missing target")
+ }
+ if t.createTime.IsZero() || t.createTime.Equal(time.Time{}) {
+ return fmt.Errorf("missing creation time")
+ }
+ if !core.TargetExist(t.target) {
+ return fmt.Errorf("unknown target")
+ }
+ return nil
+}
+
+func (t *Token) ToConfig() map[string]string {
+ return map[string]string{
+ tokenValueKey: t.Value,
+ }
+}
diff --git a/bridge/core/bridge.go b/bridge/core/bridge.go
index 1cad10e9..9a46e7b1 100644
--- a/bridge/core/bridge.go
+++ b/bridge/core/bridge.go
@@ -13,7 +13,6 @@ import (
"github.com/pkg/errors"
"github.com/MichaelMure/git-bug/cache"
- "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
)
@@ -21,10 +20,9 @@ var ErrImportNotSupported = errors.New("import is not supported")
var ErrExportNotSupported = errors.New("export is not supported")
const (
- ConfigKeyTarget = "target"
- ConfigKeyToken = "token"
- ConfigKeyTokenId = "token-id"
- MetaKeyOrigin = "origin"
+ ConfigKeyTarget = "target"
+
+ MetaKeyOrigin = "origin"
bridgeConfigKeyPrefix = "git-bug.bridge"
)
@@ -37,9 +35,8 @@ type BridgeParams struct {
Owner string
Project string
URL string
- Token string
- TokenId string
- TokenStdin bool
+ CredPrefix string
+ TokenRaw string
}
// Bridge is a wrapper around a BridgeImpl that will bind low-level
@@ -143,7 +140,7 @@ func DefaultBridge(repo *cache.RepoCache) (*Bridge, error) {
// ConfiguredBridges return the list of bridge that are configured for the given
// repo
-func ConfiguredBridges(repo repository.RepoCommon) ([]string, error) {
+func ConfiguredBridges(repo repository.RepoConfig) ([]string, error) {
configs, err := repo.LocalConfig().ReadAll(bridgeConfigKeyPrefix + ".")
if err != nil {
return nil, errors.Wrap(err, "can't read configured bridges")
@@ -178,7 +175,7 @@ func ConfiguredBridges(repo repository.RepoCommon) ([]string, error) {
}
// Check if a bridge exist
-func BridgeExist(repo repository.RepoCommon, name string) bool {
+func BridgeExist(repo repository.RepoConfig, name string) bool {
keyPrefix := fmt.Sprintf("git-bug.bridge.%s.", name)
conf, err := repo.LocalConfig().ReadAll(keyPrefix)
@@ -187,7 +184,7 @@ func BridgeExist(repo repository.RepoCommon, name string) bool {
}
// Remove a configured bridge
-func RemoveBridge(repo repository.RepoCommon, name string) error {
+func RemoveBridge(repo repository.RepoConfig, name string) error {
re, err := regexp.Compile(`^[a-zA-Z0-9]+`)
if err != nil {
panic(err)
@@ -242,7 +239,7 @@ func (b *Bridge) ensureConfig() error {
return nil
}
-func loadConfig(repo repository.RepoCommon, name string) (Configuration, error) {
+func loadConfig(repo repository.RepoConfig, name string) (Configuration, error) {
keyPrefix := fmt.Sprintf("git-bug.bridge.%s.", name)
pairs, err := repo.LocalConfig().ReadAll(keyPrefix)
@@ -280,16 +277,9 @@ func (b *Bridge) ensureInit() error {
return nil
}
- token, err := LoadToken(b.repo, entity.Id(b.conf[ConfigKeyTokenId]))
- if err != nil {
- return err
- }
-
- b.conf[ConfigKeyToken] = token.Value
-
importer := b.getImporter()
if importer != nil {
- err := importer.Init(b.conf)
+ err := importer.Init(b.repo, b.conf)
if err != nil {
return err
}
@@ -297,7 +287,7 @@ func (b *Bridge) ensureInit() error {
exporter := b.getExporter()
if exporter != nil {
- err := exporter.Init(b.conf)
+ err := exporter.Init(b.repo, b.conf)
if err != nil {
return err
}
diff --git a/bridge/core/interfaces.go b/bridge/core/interfaces.go
index 047f3880..77e0a7b9 100644
--- a/bridge/core/interfaces.go
+++ b/bridge/core/interfaces.go
@@ -5,7 +5,6 @@ import (
"time"
"github.com/MichaelMure/git-bug/cache"
- "github.com/MichaelMure/git-bug/repository"
)
type Configuration map[string]string
@@ -16,7 +15,7 @@ type BridgeImpl interface {
// Configure handle the user interaction and return a key/value configuration
// for future use
- Configure(repo repository.RepoCommon, params BridgeParams) (Configuration, error)
+ Configure(repo *cache.RepoCache, params BridgeParams) (Configuration, error)
// ValidateConfig check the configuration for error
ValidateConfig(conf Configuration) error
@@ -29,11 +28,11 @@ type BridgeImpl interface {
}
type Importer interface {
- Init(conf Configuration) error
+ Init(repo *cache.RepoCache, conf Configuration) error
ImportAll(ctx context.Context, repo *cache.RepoCache, since time.Time) (<-chan ImportResult, error)
}
type Exporter interface {
- Init(conf Configuration) error
+ Init(repo *cache.RepoCache, conf Configuration) error
ExportAll(ctx context.Context, repo *cache.RepoCache, since time.Time) (<-chan ExportResult, error)
}
diff --git a/bridge/core/token.go b/bridge/core/token.go
deleted file mode 100644
index 28c64f5c..00000000
--- a/bridge/core/token.go
+++ /dev/null
@@ -1,296 +0,0 @@
-package core
-
-import (
- "crypto/sha256"
- "errors"
- "fmt"
- "regexp"
- "sort"
- "strings"
- "time"
-
- "github.com/MichaelMure/git-bug/entity"
- "github.com/MichaelMure/git-bug/repository"
-)
-
-const (
- tokenConfigKeyPrefix = "git-bug.token"
- tokenValueKey = "value"
- tokenTargetKey = "target"
- tokenCreateTimeKey = "createtime"
-)
-
-var ErrTokenNotExist = errors.New("token doesn't exist")
-
-func NewErrMultipleMatchToken(matching []entity.Id) *entity.ErrMultipleMatch {
- return entity.NewErrMultipleMatch("token", matching)
-}
-
-// Token holds an API access token data
-type Token struct {
- Value string
- Target string
- CreateTime time.Time
-}
-
-// NewToken instantiate a new token
-func NewToken(value, target string) *Token {
- return &Token{
- Value: value,
- Target: target,
- CreateTime: time.Now(),
- }
-}
-
-func (t *Token) ID() entity.Id {
- sum := sha256.Sum256([]byte(t.Target + t.Value))
- return entity.Id(fmt.Sprintf("%x", sum))
-}
-
-// Validate ensure token important fields are valid
-func (t *Token) Validate() error {
- if t.Value == "" {
- return fmt.Errorf("missing value")
- }
- if t.Target == "" {
- return fmt.Errorf("missing target")
- }
- if t.CreateTime.IsZero() || t.CreateTime.Equal(time.Time{}) {
- return fmt.Errorf("missing creation time")
- }
- if !TargetExist(t.Target) {
- return fmt.Errorf("unknown target")
- }
- return nil
-}
-
-// LoadToken loads a token from the repo config
-func LoadToken(repo repository.RepoCommon, id entity.Id) (*Token, error) {
- keyPrefix := fmt.Sprintf("git-bug.token.%s.", id)
-
- // read token config pairs
- rawconfigs, err := repo.GlobalConfig().ReadAll(keyPrefix)
- if err != nil {
- // Not exactly right due to the limitation of ReadAll()
- return nil, ErrTokenNotExist
- }
-
- // trim key prefix
- configs := make(map[string]string)
- for key, value := range rawconfigs {
- newKey := strings.TrimPrefix(key, keyPrefix)
- configs[newKey] = value
- }
-
- token := &Token{}
-
- token.Value = configs[tokenValueKey]
- token.Target = configs[tokenTargetKey]
- if createTime, ok := configs[tokenCreateTimeKey]; ok {
- if t, err := repository.ParseTimestamp(createTime); err == nil {
- token.CreateTime = t
- }
- }
-
- return token, nil
-}
-
-// LoadTokenPrefix load a token from the repo config with a prefix
-func LoadTokenPrefix(repo repository.RepoCommon, prefix string) (*Token, error) {
- tokens, err := ListTokens(repo)
- if err != nil {
- return nil, err
- }
-
- // preallocate but empty
- matching := make([]entity.Id, 0, 5)
-
- for _, id := range tokens {
- if id.HasPrefix(prefix) {
- matching = append(matching, id)
- }
- }
-
- if len(matching) > 1 {
- return nil, NewErrMultipleMatchToken(matching)
- }
-
- if len(matching) == 0 {
- return nil, ErrTokenNotExist
- }
-
- return LoadToken(repo, matching[0])
-}
-
-// ListTokens list all existing token ids
-func ListTokens(repo repository.RepoCommon) ([]entity.Id, error) {
- configs, err := repo.GlobalConfig().ReadAll(tokenConfigKeyPrefix + ".")
- if err != nil {
- return nil, err
- }
-
- re, err := regexp.Compile(tokenConfigKeyPrefix + `.([^.]+)`)
- if err != nil {
- panic(err)
- }
-
- set := make(map[string]interface{})
-
- for key := range configs {
- res := re.FindStringSubmatch(key)
-
- if res == nil {
- continue
- }
-
- set[res[1]] = nil
- }
-
- result := make([]entity.Id, 0, len(set))
- for key := range set {
- result = append(result, entity.Id(key))
- }
-
- sort.Sort(entity.Alphabetical(result))
-
- return result, nil
-}
-
-// ListTokensWithTarget list all token ids associated with the target
-func ListTokensWithTarget(repo repository.RepoCommon, target string) ([]entity.Id, error) {
- var ids []entity.Id
- tokensIds, err := ListTokens(repo)
- if err != nil {
- return nil, err
- }
-
- for _, tokenId := range tokensIds {
- token, err := LoadToken(repo, tokenId)
- if err != nil {
- return nil, err
- }
-
- if token.Target == target {
- ids = append(ids, tokenId)
- }
- }
- return ids, nil
-}
-
-// LoadTokens load all existing tokens
-func LoadTokens(repo repository.RepoCommon) ([]*Token, error) {
- tokensIds, err := ListTokens(repo)
- if err != nil {
- return nil, err
- }
-
- var tokens []*Token
- for _, id := range tokensIds {
- token, err := LoadToken(repo, id)
- if err != nil {
- return nil, err
- }
- tokens = append(tokens, token)
- }
- return tokens, nil
-}
-
-// LoadTokensWithTarget load all existing tokens for a given target
-func LoadTokensWithTarget(repo repository.RepoCommon, target string) ([]*Token, error) {
- tokensIds, err := ListTokens(repo)
- if err != nil {
- return nil, err
- }
-
- var tokens []*Token
- for _, id := range tokensIds {
- token, err := LoadToken(repo, id)
- if err != nil {
- return nil, err
- }
- if token.Target == target {
- tokens = append(tokens, token)
- }
- }
- return tokens, nil
-}
-
-// TokenIdExist return wether token id exist or not
-func TokenIdExist(repo repository.RepoCommon, id entity.Id) bool {
- _, err := LoadToken(repo, id)
- return err == nil
-}
-
-// TokenExist return wether there is a token with a certain value or not
-func TokenExist(repo repository.RepoCommon, value string) bool {
- tokens, err := LoadTokens(repo)
- if err != nil {
- return false
- }
- for _, token := range tokens {
- if token.Value == value {
- return true
- }
- }
- return false
-}
-
-// TokenExistWithTarget same as TokenExist but restrict search for a given target
-func TokenExistWithTarget(repo repository.RepoCommon, value string, target string) bool {
- tokens, err := LoadTokensWithTarget(repo, target)
- if err != nil {
- return false
- }
- for _, token := range tokens {
- if token.Value == value {
- return true
- }
- }
- return false
-}
-
-// StoreToken stores a token in the repo config
-func StoreToken(repo repository.RepoCommon, token *Token) error {
- storeValueKey := fmt.Sprintf("git-bug.token.%s.%s", token.ID().String(), tokenValueKey)
- err := repo.GlobalConfig().StoreString(storeValueKey, token.Value)
- if err != nil {
- return err
- }
-
- storeTargetKey := fmt.Sprintf("git-bug.token.%s.%s", token.ID().String(), tokenTargetKey)
- err = repo.GlobalConfig().StoreString(storeTargetKey, token.Target)
- if err != nil {
- return err
- }
-
- createTimeKey := fmt.Sprintf("git-bug.token.%s.%s", token.ID().String(), tokenCreateTimeKey)
- return repo.GlobalConfig().StoreTimestamp(createTimeKey, token.CreateTime)
-}
-
-// RemoveToken removes a token from the repo config
-func RemoveToken(repo repository.RepoCommon, id entity.Id) error {
- keyPrefix := fmt.Sprintf("git-bug.token.%s", id)
- return repo.GlobalConfig().RemoveAll(keyPrefix)
-}
-
-// LoadOrCreateToken will try to load a token matching the same value or create it
-func LoadOrCreateToken(repo repository.RepoCommon, target, tokenValue string) (*Token, error) {
- tokens, err := LoadTokensWithTarget(repo, target)
- if err != nil {
- return nil, err
- }
-
- for _, token := range tokens {
- if token.Value == tokenValue {
- return token, nil
- }
- }
-
- token := NewToken(tokenValue, target)
- err = StoreToken(repo, token)
- if err != nil {
- return nil, err
- }
-
- return token, nil
-}