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 }