github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/store/config.go (about)

     1  /*
     2   * Copyright (c) 2018-2020 vChain, Inc. All Rights Reserved.
     3   * This software is released under GPL3.
     4   * The full license information can be found under:
     5   * https://www.gnu.org/licenses/gpl-3.0.en.html
     6   *
     7   */
     8  
     9  package store
    10  
    11  import (
    12  	"errors"
    13  	"fmt"
    14  	"os"
    15  	"path/filepath"
    16  
    17  	"github.com/spf13/viper"
    18  )
    19  
    20  const (
    21  	configSchemaVer uint = 3
    22  )
    23  
    24  // User holds user's configuration.
    25  type User struct {
    26  	Email    string `json:"email,omitempty"`
    27  	Token    string `json:"token,omitempty"`
    28  	KeyStore string `json:"keystore,omitempty"`
    29  	LcCert   string `json:"lcCert,omitempty"`
    30  }
    31  
    32  // ConfigRoot holds root fields of the configuration file.
    33  type ConfigRoot struct {
    34  	SchemaVersion  uint           `json:"schemaVersion"`
    35  	Users          []*User        `json:"users"`
    36  	CurrentContext CurrentContext `json:"currentContext"`
    37  }
    38  
    39  type CurrentContext struct {
    40  	Email           string `json:"email,omitempty"`
    41  	LcHost          string `json:"LcHost,omitempty"`
    42  	LcPort          string `json:"LcPort,omitempty"`
    43  	LcCert          string `json:"LcCert,omitempty"`
    44  	LcSkipTlsVerify bool   `json:"LcSkipTlsVerify,omitempty"`
    45  	LcNoTls         bool   `json:"LcNoTls,omitempty"`
    46  }
    47  
    48  func (cc *CurrentContext) Clear() {
    49  	cc.Email = ""
    50  	cc.LcHost = ""
    51  	cc.LcPort = ""
    52  	cc.LcCert = ""
    53  	cc.LcSkipTlsVerify = false
    54  	cc.LcNoTls = false
    55  }
    56  
    57  var cfg *ConfigRoot
    58  var v = viper.New()
    59  
    60  // Config returns the global config instance
    61  func Config() *ConfigRoot {
    62  	return cfg
    63  }
    64  
    65  func setupConfigFile() string {
    66  	cfgFile := ConfigFile()
    67  	v.SetConfigFile(cfgFile)
    68  	v.SetConfigPermissions(FilePerm)
    69  	return cfgFile
    70  }
    71  
    72  // LoadConfig loads the global configuration from file
    73  func LoadConfig() error {
    74  
    75  	// Make default config
    76  	c := ConfigRoot{
    77  		SchemaVersion: configSchemaVer,
    78  	}
    79  	cfg = &c
    80  
    81  	// Setup config file
    82  	cfgFile := setupConfigFile()
    83  
    84  	SetDir(filepath.Dir(cfgFile))
    85  
    86  	// Ensure working dir
    87  	if err := ensureDir(dir); err != nil {
    88  		return err
    89  	}
    90  
    91  	// Create default file if it does not exist yet
    92  	if ConfigFile() == defaultConfigFilepath() {
    93  		if _, err := os.Stat(cfgFile); os.IsNotExist(err) {
    94  			sErr := SaveConfig()
    95  			return sErr
    96  		}
    97  	}
    98  
    99  	if err := v.ReadInConfig(); err != nil {
   100  		return err
   101  	}
   102  
   103  	if err := v.Unmarshal(&c); err != nil {
   104  		oldFormat := ConfigRootV2{
   105  			SchemaVersion: 2,
   106  		}
   107  		if err := v.Unmarshal(&oldFormat); err != nil {
   108  			return errors.New("unable to parse config file")
   109  		}
   110  		fmt.Println("Upgrading config to new format. Old sessions will expire")
   111  		c.Users = []*User{}
   112  		c.CurrentContext.Email = oldFormat.CurrentContext
   113  		c.SchemaVersion = 3
   114  	}
   115  
   116  	return SaveConfig()
   117  }
   118  
   119  // SaveConfig stores the current configuration to file
   120  func SaveConfig() error {
   121  	// Setup config file
   122  	setupConfigFile()
   123  
   124  	// Ensure working dir
   125  	if err := ensureDir(dir); err != nil {
   126  		return err
   127  	}
   128  
   129  	cfg.SchemaVersion = configSchemaVer
   130  	v.Set("users", cfg.Users)
   131  	v.Set("currentContext", cfg.CurrentContext)
   132  	v.Set("schemaVersion", cfg.SchemaVersion)
   133  	return v.WriteConfig()
   134  }
   135  
   136  // User returns an User from the global config matching the given email.
   137  // User returns nil when an empty email is given or c is nil.
   138  func (c *ConfigRoot) UserByMail(email string) *User {
   139  	defer func() {
   140  		if cfg != nil {
   141  			cfg.CurrentContext.Clear()
   142  			cfg.CurrentContext.Email = email
   143  		}
   144  	}()
   145  	if c == nil || email == "" {
   146  		return nil
   147  	}
   148  
   149  	for _, u := range c.Users {
   150  		if u.Email == email {
   151  			return u
   152  		}
   153  	}
   154  
   155  	u := User{
   156  		Email: email,
   157  	}
   158  
   159  	c.Users = append(c.Users, &u)
   160  	return &u
   161  }
   162  
   163  // User returns an User from the global config matching the given email.
   164  // User returns nil when an empty email is given or c is nil.
   165  func (c *ConfigRoot) NewLcUser(host, port, lcCert string, lcSkipTlsVerify, lcNoTls bool) (u *CurrentContext) {
   166  	defer func() {
   167  		cfg.CurrentContext.Clear()
   168  		cfg.CurrentContext.LcHost = host
   169  		cfg.CurrentContext.LcPort = port
   170  		cfg.CurrentContext.LcCert = lcCert
   171  		cfg.CurrentContext.LcSkipTlsVerify = lcSkipTlsVerify
   172  		cfg.CurrentContext.LcNoTls = lcNoTls
   173  	}()
   174  
   175  	return u
   176  }
   177  
   178  // RemoveUser removes an user from config matching the given email, if not found return false
   179  func (c *ConfigRoot) RemoveUserByMail(email string) bool {
   180  	if c == nil {
   181  		return false
   182  	}
   183  
   184  	for i, u := range c.Users {
   185  		if u.Email == email {
   186  			c.Users = append(c.Users[:i], c.Users[i+1:]...)
   187  			return true
   188  		}
   189  	}
   190  	return false
   191  }
   192  
   193  // ClearContext clean up all auth token for all users and set an empty context.
   194  func (c *ConfigRoot) ClearContext() {
   195  	if c == nil {
   196  		return
   197  	}
   198  	for _, u := range c.Users {
   199  		u.Token = ""
   200  	}
   201  	c.CurrentContext = CurrentContext{}
   202  }
   203  
   204  func CNLCContext() bool {
   205  	cfg := Config()
   206  	return cfg.CurrentContext.LcHost != ""
   207  }
   208  
   209  func CNioContext() bool {
   210  	cfg := Config()
   211  	return cfg.CurrentContext.Email != ""
   212  }