aboutsummaryrefslogtreecommitdiffstats
path: root/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'bridge')
-rw-r--r--bridge/bridges.go12
-rw-r--r--bridge/core/bridge.go6
-rw-r--r--bridge/core/token.go182
-rw-r--r--bridge/github/github.go4
-rw-r--r--bridge/gitlab/gitlab.go4
-rw-r--r--bridge/launchpad/launchpad.go4
6 files changed, 197 insertions, 15 deletions
diff --git a/bridge/bridges.go b/bridge/bridges.go
index dcb35af1..9bbf3941 100644
--- a/bridge/bridges.go
+++ b/bridge/bridges.go
@@ -3,13 +3,19 @@ package bridge
import (
"github.com/MichaelMure/git-bug/bridge/core"
- _ "github.com/MichaelMure/git-bug/bridge/github"
- _ "github.com/MichaelMure/git-bug/bridge/gitlab"
- _ "github.com/MichaelMure/git-bug/bridge/launchpad"
+ "github.com/MichaelMure/git-bug/bridge/github"
+ "github.com/MichaelMure/git-bug/bridge/gitlab"
+ "github.com/MichaelMure/git-bug/bridge/launchpad"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/repository"
)
+func init() {
+ core.Register(&github.Github{})
+ core.Register(&gitlab.Gitlab{})
+ core.Register(&launchpad.Launchpad{})
+}
+
// Targets return all known bridge implementation target
func Targets() []string {
return core.Targets()
diff --git a/bridge/core/bridge.go b/bridge/core/bridge.go
index ddf041f1..e419ed77 100644
--- a/bridge/core/bridge.go
+++ b/bridge/core/bridge.go
@@ -71,6 +71,12 @@ func Targets() []string {
return result
}
+// TargetExist return true if the given target has a bridge implementation
+func TargetExist(target string) bool {
+ _, ok := bridgeImpl[target]
+ return ok
+}
+
// Instantiate a new Bridge for a repo, from the given target and name
func NewBridge(repo *cache.RepoCache, target string, name string) (*Bridge, error) {
implType, ok := bridgeImpl[target]
diff --git a/bridge/core/token.go b/bridge/core/token.go
new file mode 100644
index 00000000..2ceabca2
--- /dev/null
+++ b/bridge/core/token.go
@@ -0,0 +1,182 @@
+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.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 return a map representing the stored tokens in the repo config and global config
+// along with their type (global: true, local:false)
+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
+}
+
+// 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)
+}
diff --git a/bridge/github/github.go b/bridge/github/github.go
index 176bdd84..e4fb03dd 100644
--- a/bridge/github/github.go
+++ b/bridge/github/github.go
@@ -10,10 +10,6 @@ import (
"github.com/MichaelMure/git-bug/bridge/core"
)
-func init() {
- core.Register(&Github{})
-}
-
type Github struct{}
func (*Github) Target() string {
diff --git a/bridge/gitlab/gitlab.go b/bridge/gitlab/gitlab.go
index f4b980ac..05721bfe 100644
--- a/bridge/gitlab/gitlab.go
+++ b/bridge/gitlab/gitlab.go
@@ -23,10 +23,6 @@ const (
defaultTimeout = 60 * time.Second
)
-func init() {
- core.Register(&Gitlab{})
-}
-
type Gitlab struct{}
func (*Gitlab) Target() string {
diff --git a/bridge/launchpad/launchpad.go b/bridge/launchpad/launchpad.go
index 1fd9edc2..030d9169 100644
--- a/bridge/launchpad/launchpad.go
+++ b/bridge/launchpad/launchpad.go
@@ -5,10 +5,6 @@ import (
"github.com/MichaelMure/git-bug/bridge/core"
)
-func init() {
- core.Register(&Launchpad{})
-}
-
type Launchpad struct{}
func (*Launchpad) Target() string {