aboutsummaryrefslogblamecommitdiffstats
path: root/bridge/core/token.go
blob: 9e39364217bf6a8490428326f83ea9a97025763e (plain) (tree)
1
2
3
4
5
6
7
8
9







                 
                                                   









                                              
                                             







                       
                                   









                                                                                

                                                   











                                                         
                                                                                      


                                                          

                                  












                                                              
                          









                                                         
                                                           



                                                 
                                                         


                                                 
                                                            












                                                               

                                                                        


                                           

                                                                              


                                          
                                                                            








































                                                                                 

                                                                 


                                      

                                                                         


                                     
                                                                 


































                                                                                        


                                                                                                

 


                                                                                                      

 

                                                                 



                                                          

                                                                       


                                                          
package core

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/MichaelMure/git-bug/repository"
)

const (
	tokenConfigKeyPrefix = "git-bug.token"
	tokenKeyValue        = "value"
	tokenKeyTarget       = "target"
	tokenKeyGlobal       = "global"
	tokenKeyScopes       = "scopes"
)

// Token represent token related informations
type Token struct {
	Name   string
	Value  string
	Target string
	Global bool
	Scopes []string
}

// NewToken instantiate a new token
func NewToken(name, value, target string, global bool, scopes []string) *Token {
	return &Token{
		Name:   name,
		Value:  value,
		Target: target,
		Global: global,
		Scopes: scopes,
	}
}

// Validate ensure token important fields are valid
func (t *Token) Validate() error {
	if t.Name == "" {
		return fmt.Errorf("missing token name")
	}
	if t.Value == "" {
		return fmt.Errorf("missing token value")
	}
	if t.Target == "" {
		return fmt.Errorf("missing token target")
	}
	return nil
}

func loadToken(repo repository.RepoConfig, name string, global bool) (*Token, error) {
	keyPrefix := fmt.Sprintf("git-bug.token.%s", name)
	var pairs map[string]string
	var err error

	// read token config pairs
	if global {
		pairs, err = repo.ReadGlobalConfigs(keyPrefix)
		if err != nil {
			return nil, err
		}

	} else {
		pairs, err = repo.ReadConfigs(keyPrefix)
		if err != nil {
			return nil, err
		}
	}

	// trim key prefix
	result := make(Configuration, len(pairs))
	for key, value := range pairs {
		key := strings.TrimPrefix(key, keyPrefix)
		result[key] = value
	}

	var ok bool
	token := &Token{Name: name}
	token.Value, ok = result[tokenKeyValue]
	if !ok {
		return nil, fmt.Errorf("empty token value")
	}

	token.Target, ok = result[tokenKeyTarget]
	if !ok {
		return nil, fmt.Errorf("empty token key")
	}

	if g, ok := result[tokenKeyGlobal]; !ok {
		return nil, fmt.Errorf("empty token global")
	} else if g == "true" {
		token.Global = true
	}

	scopesString, ok := result[tokenKeyScopes]
	if !ok {
		return nil, fmt.Errorf("missing scopes config")
	}

	token.Scopes = strings.Split(scopesString, ",")
	return token, nil
}

// GetToken loads a token from repo config
func GetToken(repo repository.RepoConfig, name string) (*Token, error) {
	return loadToken(repo, name, false)
}

// GetGlobalToken loads a token from the global config
func GetGlobalToken(repo repository.RepoConfig, name string) (*Token, error) {
	return loadToken(repo, name, true)
}

func listTokens(repo repository.RepoConfig, global bool) ([]string, error) {
	var configs map[string]string
	var err error
	if global {
		configs, err = repo.ReadConfigs(tokenConfigKeyPrefix + ".")
		if err != nil {
			return nil, err
		}
	} else {
		configs, err = repo.ReadGlobalConfigs(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([]string, len(set))
	i := 0
	for key := range set {
		result[i] = key
		i++
	}

	return result, nil
}

// ListTokens return the list of stored tokens in the repo config
func ListTokens(repo repository.RepoConfig) ([]string, error) {
	return listTokens(repo, false)
}

// ListGlobalTokens return the list of stored tokens in the global config
func ListGlobalTokens(repo repository.RepoConfig) ([]string, error) {
	return listTokens(repo, true)
}

func storeToken(repo repository.RepoConfig, token *Token) error {
	var store func(key, value string) error
	if token.Global {
		store = repo.StoreGlobalConfig
	} else {
		store = repo.StoreConfig
	}

	var err error
	storeValueKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyValue)
	err = store(storeValueKey, token.Value)
	if err != nil {
		return err
	}

	storeTargetKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyTarget)
	err = store(storeTargetKey, token.Target)
	if err != nil {
		return err
	}

	storeGlobalKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyGlobal)
	err = store(storeGlobalKey, strconv.FormatBool(token.Global))
	if err != nil {
		return err
	}

	storeScopesKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyScopes)
	err = store(storeScopesKey, strings.Join(token.Scopes, ","))
	if err != nil {
		return err
	}

	return nil
}

// StoreToken stores a token in the repo config
func StoreToken(repo repository.RepoConfig, name, value, target string, scopes []string) error {
	return storeToken(repo, NewToken(name, value, target, false, scopes))
}

// StoreGlobalToken stores a token in global config
func StoreGlobalToken(repo repository.RepoConfig, name, value, target string, scopes []string) error {
	return storeToken(repo, NewToken(name, value, target, true, scopes))
}

// RemoveToken removes a token from the repo config
func RemoveToken(repo repository.RepoConfig, name string) error {
	keyPrefix := fmt.Sprintf("git-bug.token.%s", name)
	return repo.RmConfigs(keyPrefix)
}

// RemoveGlobalToken removes a token from the repo config
func RemoveGlobalToken(repo repository.RepoConfig, name string) error {
	keyPrefix := fmt.Sprintf("git-bug.token.%s", name)
	return repo.RmGlobalConfigs(keyPrefix)
}