Skip to content

Commit

Permalink
Add info command (#129)
Browse files Browse the repository at this point in the history
This commit adds a command to display info such as org Id, org name,
email used, type of token etc. This should make it easier to debug
users' request failures.
  • Loading branch information
narasaka authored Nov 17, 2023
1 parent 4b8acea commit cfff780
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 3 deletions.
2 changes: 1 addition & 1 deletion foxglove/cmd/configure_api_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func newConfigureAPIKeyCommand() *cobra.Command {
prompt := fmt.Sprintf("Enter an API key (will be written to %s):\n", viper.ConfigFileUsed())
token = promptForInput(prompt)
}
err := configureAuth(token, defaultString(baseURL, defaultBaseURL))
err := configureAuth(token, defaultString(baseURL, defaultBaseURL), TokenApiKey)
if err != nil {
dief("Configuration failed: %s", err)
}
Expand Down
64 changes: 64 additions & 0 deletions foxglove/cmd/info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package cmd

import (
"fmt"
"os"
"strconv"

"github.com/foxglove/foxglove-cli/foxglove/console"
tw "github.com/foxglove/foxglove-cli/foxglove/util/tablewriter"

"github.com/spf13/cobra"
)

func executeInfo(baseURL, clientID, token, userAgent string) error {
isUsingApiKey := TokenIsApiKey(token)
if isUsingApiKey {
fmt.Println("Authenticated with API key")
return nil
}

client := console.NewRemoteFoxgloveClient(baseURL, clientID, token, userAgent)
me, err := client.Me()
if err != nil {
return err
}

headers := []string{
"Email",
"Email verified",
"Org ID",
"Org Slug",
"Admin",
}
data := [][]string{{
me.Email,
strconv.FormatBool(me.EmailVerified),
me.OrgId,
me.OrgSlug,
strconv.FormatBool(me.Admin),
}}

fmt.Println("Authenticated with session token")
tw.PrintTable(os.Stdout, headers, data)

return nil
}

func newInfoCommand(params *baseParams) *cobra.Command {
loginCmd := &cobra.Command{
Use: "info",
Short: "Display information about the currently authenticated user",
Run: func(cmd *cobra.Command, args []string) {
if !IsAuthenticated() {
dief("Not signed in. Run `foxglove auth login` or `foxglove auth configure-api-key` to continue.")
}
err := executeInfo(params.baseURL, *params.clientID, params.token, params.userAgent)
if err != nil {
dief("Info command failed: %s", err)
}
},
}
loginCmd.InheritedFlags()
return loginCmd
}
2 changes: 1 addition & 1 deletion foxglove/cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func executeLogin(baseURL, clientID, userAgent string, authDelegate console.Auth
if err != nil {
return err
}
err = configureAuth(bearerToken, baseURL)
err = configureAuth(bearerToken, baseURL, TokenSession)
if err != nil {
return fmt.Errorf("Failed to configure auth: %w", err)
}
Expand Down
13 changes: 12 additions & 1 deletion foxglove/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,18 @@ func configfile() (string, error) {
return path.Join(home, ".foxgloverc"), nil
}

func configureAuth(token, baseURL string) error {
type AuthType int

const (
Unknown AuthType = iota
TokenSession
TokenApiKey
)

func configureAuth(token, baseURL string, authType AuthType) error {
viper.Set("bearer_token", token)
viper.Set("base_url", baseURL)
viper.Set("auth_type", authType)
err := viper.WriteConfigAs(viper.ConfigFileUsed())
if err != nil {
return fmt.Errorf("Failed to write config: %w", err)
Expand Down Expand Up @@ -194,9 +203,11 @@ func Execute(version string) {
return
}
loginCmd := newLoginCommand(params)
infoCmd := newInfoCommand(params)
configureAPIKey := newConfigureAPIKeyCommand()
authCmd.AddCommand(loginCmd)
authCmd.AddCommand(configureAPIKey)
authCmd.AddCommand(infoCmd)
recordingsCmd.AddCommand(newListRecordingsCommand(params))
importsCmd.AddCommand(newListImportsCommand(params), addImportCmd)
attachmentsCmd.AddCommand(newListAttachmentsCommand(params))
Expand Down
19 changes: 19 additions & 0 deletions foxglove/cmd/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (
"fmt"
"io"
"os"
"strings"
"time"

"github.com/foxglove/foxglove-cli/foxglove/console"
tw "github.com/foxglove/foxglove-cli/foxglove/util/tablewriter"
"github.com/foxglove/mcap/go/mcap"
"github.com/relvacode/iso8601"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var ErrTruncatedMCAP = errors.New("truncated mcap file")
Expand Down Expand Up @@ -228,3 +230,20 @@ func maybeConvertToRFC3339(timestamp string) (string, error) {
}
return parsed.Format(time.RFC3339), nil
}

func TokenIsApiKey(token string) bool {
authType := viper.GetInt("auth_type")
switch AuthType(authType) {
case TokenApiKey:
return true
case TokenSession:
return false
default:
return strings.HasPrefix(token, "fox_sk_")
}
}

func IsAuthenticated() bool {
token := viper.GetString("bearer_token")
return token != ""
}
12 changes: 12 additions & 0 deletions foxglove/console/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,18 @@ type ImportFromEdgeResponse struct {
ImportStatus string `json:"importStatus"`
}

type MeRequest struct{}

type MeResponse struct {
ID string `json:"id"`
OrgId string `json:"orgId"`
OrgDisplayName string `json:"orgDisplayName"`
OrgSlug string `json:"orgSlug"`
Email string `json:"email"`
EmailVerified bool `json:"emailVerified"`
Admin bool `json:"admin"`
}

func requiredVal(val *string) string {
if val != nil {
return *val
Expand Down
6 changes: 6 additions & 0 deletions foxglove/console/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,12 @@ func (c *FoxgloveClient) ImportFromEdge(req ImportFromEdgeRequest, id string) (r
return resp, err
}

func (c *FoxgloveClient) Me() (resp MeResponse, err error) {
req := MeRequest{}
err = c.get("/v1/me", req, &resp)
return resp, err
}

// Token returns a token for the provided device code. If the token for the
// device code does not exist yet, ErrForbidden is returned. It is up to the
// caller to give up after sufficient retries.
Expand Down

0 comments on commit cfff780

Please sign in to comment.