diff --git a/cmd/common/config.go b/cmd/common/config.go index 9f66df9..967aad7 100644 --- a/cmd/common/config.go +++ b/cmd/common/config.go @@ -1,6 +1,7 @@ package common import ( + "encoding/json" "fmt" "log" "os" @@ -30,6 +31,7 @@ const ( AccountConfigKeyPartial = "account" // app-scoped account ID key OrganizationConfigKeyPartial = "organization" // app-scoped organization ID key WalletConfigKeyPartial = "wallet" // app-scoped HD wallet ID key + UserInfoConfigKey = "prvd-user-info" // details of the currently auth'd user ) var CfgFile string @@ -76,6 +78,34 @@ func InitConfig() { } } +func StoreUserDetails(user *ident.User) error { + json, err := json.Marshal(user) + if err != nil { + log.Printf("Error storing user details; %s", err) + return err + } + + viper.Set(UserInfoConfigKey, string(json)) + viper.WriteConfig() + + return nil +} + +func GetUserDetails() (*ident.User, error) { + if viper.IsSet(UserInfoConfigKey) { + raw := viper.GetString(UserInfoConfigKey) + var user ident.User + err := json.Unmarshal([]byte(raw), &user) + if err != nil { + return nil, err + } + + return &user, nil + } + + return nil, fmt.Errorf("please authenticate to retrieve your user info") +} + func RequireUserAccessToken() string { token := "" if viper.IsSet(AccessTokenConfigKey) { @@ -217,29 +247,11 @@ func BuildConfigKeyWithUser(keyPartial, userID string) string { } func isTokenExpired(bearerToken string) bool { - token, err := jwt.Parse(bearerToken, func(_jwtToken *jwt.Token) (interface{}, error) { - // uncomment when enabling local verification - // var kid *string - // if kidhdr, ok := _jwtToken.Header["kid"].(string); ok { - // kid = &kidhdr - // } - - // publicKey, _, _, _ := util.ResolveJWTKeypair(kid) - // if publicKey == nil { - // msg := "failed to resolve a valid JWT verification key" - // if kid != nil { - // msg = fmt.Sprintf("%s; invalid kid specified in header: %s", msg, *kid) - // } else { - // msg = fmt.Sprintf("%s; no default verification key configured", msg) - // } - // return nil, fmt.Errorf(msg) - // } - - return nil, nil - }) - + var jwtParser jwt.Parser + token, _, err := jwtParser.ParseUnverified(bearerToken, jwt.MapClaims{}) if err != nil { - return false + log.Printf("failed to parse JWT token on behalf of authorized user; %s", err.Error()) + os.Exit(1) } claims := token.Claims.(jwt.MapClaims) diff --git a/cmd/info/info.go b/cmd/info/info.go new file mode 100644 index 0000000..7b35588 --- /dev/null +++ b/cmd/info/info.go @@ -0,0 +1,44 @@ +package info + +import ( + "fmt" + "log" + "os" + + "github.com/provideplatform/provide-cli/cmd/common" + "github.com/spf13/cobra" +) + +const contractTypeRegistry = "registry" + +var contract map[string]interface{} +var contracts []interface{} +var contractType string + +// InfoCmd is the handler for the `info` command +var InfoCmd = &cobra.Command{ + Use: "info", + Short: "Get information about the currently authorized user", + Long: "Get information about the currently authorized user", + Run: showInfo, +} + +func showInfo(cmd *cobra.Command, args []string) { + // User ID, email, username, .. + + user, err := common.GetUserDetails() + + if err != nil { + log.Printf("Unable to get user details: %s", err) + os.Exit(1) + } + + if user != nil { + fmt.Println("Current User:") + fmt.Println(" ID: ", user.ID) + fmt.Println(" Name: ", user.Name) + fmt.Println(" First Name: ", user.FirstName) + fmt.Println(" Last Name: ", user.LastName) + fmt.Println(" Email: ", user.Email) + } +} diff --git a/cmd/root.go b/cmd/root.go index 3a940b5..135fa1b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -14,6 +14,7 @@ import ( "github.com/provideplatform/provide-cli/cmd/common" "github.com/provideplatform/provide-cli/cmd/connectors" "github.com/provideplatform/provide-cli/cmd/contracts" + "github.com/provideplatform/provide-cli/cmd/info" "github.com/provideplatform/provide-cli/cmd/networks" "github.com/provideplatform/provide-cli/cmd/nodes" "github.com/provideplatform/provide-cli/cmd/organizations" @@ -62,6 +63,7 @@ func init() { rootCmd.AddCommand(users.UsersCmd) rootCmd.AddCommand(vaults.VaultsCmd) rootCmd.AddCommand(wallets.WalletsCmd) + rootCmd.AddCommand(info.InfoCmd) common.CacheCommands(rootCmd) } diff --git a/cmd/users/authenticate.go b/cmd/users/authenticate.go index 8f965ed..c61e075 100644 --- a/cmd/users/authenticate.go +++ b/cmd/users/authenticate.go @@ -11,7 +11,7 @@ import ( "github.com/spf13/viper" ) -// authenticateCmd represents the authenticate command +// AuthenticateCmd represents the authenticate command var AuthenticateCmd = &cobra.Command{ Use: "authenticate", Short: "Authenticate using your credentials", @@ -34,9 +34,17 @@ func authenticate(cmd *cobra.Command, args []string) { common.CacheAccessRefreshToken(resp.Token) } else if resp.Token.Token != nil { cacheAPIToken(*resp.Token.Token) + } else { + log.Println("Failed to get token from authentication response.") + os.Exit(1) } - log.Printf("Authentication successful") + log.Print("Authentication successful") + + if resp.User != nil { + common.StoreUserDetails(resp.User) + log.Printf("User ID: %s", resp.User.ID) + } } func cacheAPIToken(token string) {