diff --git a/cmd/login.go b/cmd/login.go index 302d057..74442b1 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -2,10 +2,12 @@ package cmd import ( "bufio" + "errors" "fmt" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/zalando/go-keyring" "golang.org/x/term" "lutonite.dev/gaps-cli/gaps" "lutonite.dev/gaps-cli/util" @@ -14,9 +16,9 @@ import ( ) const ( + ServiceKey = "gaps-cli" + KeyringTokenKey = "gaps.token" UsernameViperKey = "login.username" - PasswordViperKey = "login.password" - TokenValueKey = "login.token.value" TokenStudentIdKey = "login.token.studentId" TokenDateValueKey = "login.token.generatedAt" ) @@ -31,7 +33,7 @@ var ( Use: "login", Short: "Allows to login to GAPS for future commands", Run: func(cmd *cobra.Command, args []string) { - if viper.GetString(TokenValueKey) != "" { + if token, _ := getKeyringValue(KeyringTokenKey); token != "" && !loginOpts.changePassword { // Default session duration is 6 hours on GAPS if !isTokenExpired() { log.Info("User already logged in, keeping existing token") @@ -54,14 +56,16 @@ var ( username = viper.GetString(UsernameViperKey) } - if viper.GetString(PasswordViperKey) == "" || loginOpts.changePassword { + if pwd, _ := getKeyringValue(username); pwd == "" || loginOpts.changePassword { fmt.Print("Enter your HEIG-VD einet AAI password: ") passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd())) password = string(passwordBytes) fmt.Println("ok") util.CheckErr(err) } else { - password = viper.GetString(PasswordViperKey) + var err error + password, err = getKeyringValue(username) + util.CheckErr(err) } refreshToken(username, password) @@ -75,8 +79,6 @@ func init() { loginCmd.Flags().BoolVar(&loginOpts.changePassword, "clear-password", false, "reset the password stored in the config file (if any)") viper.BindPFlag(UsernameViperKey, loginCmd.Flags().Lookup("username")) - viper.BindPFlag(PasswordViperKey, loginCmd.Flags().Lookup("password")) - viper.SetDefault(TokenValueKey, "") viper.SetDefault(TokenStudentIdKey, -1) viper.SetDefault(TokenDateValueKey, time.Now().UnixMilli()) @@ -89,7 +91,8 @@ func isTokenExpired() bool { func refreshToken(username string, password string) { viper.Set(UsernameViperKey, username) - viper.Set(PasswordViperKey, password) + err := keyring.Set(ServiceKey, username, password) + util.CheckErr(err) cfg := new(gaps.ClientConfiguration) cfg.Init(viper.GetString(UrlViperKey)) @@ -107,7 +110,9 @@ func refreshToken(username string, password string) { log.Tracef("Token: %s", token) log.Tracef("Student Id: %d", studentId) - viper.Set(TokenValueKey, token) + err = keyring.Set(ServiceKey, KeyringTokenKey, token) + util.CheckErr(err) + viper.Set(TokenStudentIdKey, studentId) viper.Set(TokenDateValueKey, time.Now().UnixMilli()) @@ -116,18 +121,35 @@ func refreshToken(username string, password string) { } func buildTokenClientConfiguration() *gaps.TokenClientConfiguration { - if viper.GetString(TokenValueKey) == "" { + token, _ := getKeyringValue(KeyringTokenKey) + if token == "" { log.Fatal("No token found, please login first") } // if token is expired, refresh it if isTokenExpired() { log.Info("Token expired, attempting refresh") - refreshToken(viper.GetString(UsernameViperKey), viper.GetString(PasswordViperKey)) + + pwd, err := keyring.Get(ServiceKey, viper.GetString(UsernameViperKey)) + util.CheckErr(err) + + refreshToken(viper.GetString(UsernameViperKey), pwd) } cfg := new(gaps.TokenClientConfiguration) - cfg.InitToken(viper.GetString(UrlViperKey), viper.GetString(TokenValueKey), viper.GetUint(TokenStudentIdKey)) + cfg.InitToken(viper.GetString(UrlViperKey), token, viper.GetUint(TokenStudentIdKey)) return cfg } + +func getKeyringValue(key string) (string, error) { + secret, err := keyring.Get(ServiceKey, key) + + if errors.Is(err, keyring.ErrNotFound) { + return "", nil + } else if err != nil { + return "", err + } + + return secret, nil +} diff --git a/go.mod b/go.mod index cd5b79d..dd77ef3 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,16 @@ require ( github.com/sirupsen/logrus v1.9.0 github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.15.0 + github.com/zalando/go-keyring v0.2.3 golang.org/x/term v0.5.0 ) require ( + github.com/alessio/shellescape v1.4.1 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect + github.com/danieljoos/wincred v1.2.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -28,7 +32,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.4.2 // indirect golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect + golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.7.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 8a20747..6b5fe30 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= +github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= +github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -51,6 +53,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= +github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -66,6 +70,8 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -177,6 +183,7 @@ github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -194,6 +201,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= +github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -336,8 +345,9 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=