Skip to content

Commit

Permalink
Get rid of custom profile config manager
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniils Petrovs committed May 12, 2022
1 parent da7b3e9 commit 5b8b8c1
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 130 deletions.
5 changes: 1 addition & 4 deletions cmd/card_ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@ import (
"github.com/platogo/zube-cli/zube/models"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)

// Used to list various Zube entities, depending on the parent command name
var cardLsCmd = &cobra.Command{
Use: "ls",
Short: "List cards with given filters",
Run: func(cmd *cobra.Command, args []string) {
profile := zube.Profile{ClientId: viper.GetString("client_id"), AccessToken: viper.GetString("access_token")}

client, _ := zube.NewClientWithProfile(&profile)
client, _ := zube.NewClient()

query := newQueryFromFlags(cmd.LocalFlags())

Expand Down
8 changes: 2 additions & 6 deletions cmd/currentPerson.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

"github.com/platogo/zube-cli/zube"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// currentPersonCmd represents the currentPerson command
Expand All @@ -30,11 +29,8 @@ var currentPersonCmd = &cobra.Command{
Use: "currentPerson",
Short: "Show info about your own user",
Run: func(cmd *cobra.Command, args []string) {
// Create a profile using Viper config
profile := zube.Profile{ClientId: viper.GetString("client_id"), AccessToken: viper.GetString("access_token")}

// Prepare a client using the loaded profile
client, _ := zube.NewClientWithProfile(&profile)
// Construct a client
client, _ := zube.NewClient()

// Call public client API to fetch resource that is needed, then print formatted output
person := client.FetchCurrentPerson()
Expand Down
2 changes: 1 addition & 1 deletion cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var loginCmd = &cobra.Command{
Short: "Login to Zube with your client ID and private key.",
Long: `A command for debugging the login flow to Zube. On success, it will print your access token.`,
Run: func(cmd *cobra.Command, args []string) {
client := zube.NewClient(ClientId)
client := zube.NewClientWithId(ClientId)

privateKey, err := zube.GetPrivateKey()

Expand Down
5 changes: 1 addition & 4 deletions cmd/project_ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/platogo/zube-cli/zube"
"github.com/platogo/zube-cli/zube/models"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// projectLsCmd represents the projectLs command
Expand All @@ -33,9 +32,7 @@ var projectLsCmd = &cobra.Command{
Short: "List all Zube projects",
Long: `You can use this command to list all projects accessible to your user.`,
Run: func(cmd *cobra.Command, args []string) {
profile := zube.Profile{ClientId: viper.GetString("client_id"), AccessToken: viper.GetString("access_token")}

client, _ := zube.NewClientWithProfile(&profile)
client, _ := zube.NewClient()

projects := client.FetchProjects()
printProjects(&projects)
Expand Down
5 changes: 1 addition & 4 deletions cmd/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"

. "github.com/logrusorgru/aurora"
"github.com/platogo/zube-cli/utils"
Expand All @@ -35,15 +34,13 @@ var viewCmd = &cobra.Command{
Use: "view",
Short: "Display the title, status, body and other info about a Zube card.",
Run: func(cmd *cobra.Command, args []string) {
profile := zube.Profile{ClientId: viper.GetString("client_id"), AccessToken: viper.GetString("access_token")}

var cardNumber string

if len(args) > 0 {
cardNumber = args[0]
}

client, _ := zube.NewClientWithProfile(&profile)
client, _ := zube.NewClient()

if parentCmd := cmd.Parent().Name(); parentCmd == "card" {
cardQueryByNumber := zube.Query{Filter: zube.Filter{Where: map[string]any{"number": cardNumber}}}
Expand Down
5 changes: 1 addition & 4 deletions cmd/workspace_ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,14 @@ import (
"github.com/platogo/zube-cli/zube"
"github.com/platogo/zube-cli/zube/models"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// workspaceLsCmd represents the workspace ls command
var workspaceLsCmd = &cobra.Command{
Use: "ls",
Short: "List workspaces",
Run: func(cmd *cobra.Command, args []string) {
profile := zube.Profile{ClientId: viper.GetString("client_id"), AccessToken: viper.GetString("access_token")}

client, _ := zube.NewClientWithProfile(&profile)
client, _ := zube.NewClient()
workspaces := client.FetchWorkspaces()
printWorkspaces(&workspaces)
},
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ require (
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.11.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

require (
Expand All @@ -28,4 +27,5 @@ require (
golang.org/x/text v0.3.7 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
43 changes: 43 additions & 0 deletions zube/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package zube

import (
"crypto/rsa"
"encoding/json"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/platogo/zube-cli/zube/models"
)

const PrivateKeyFileName = "zube_api_key.pem"
Expand Down Expand Up @@ -48,3 +50,44 @@ func GenerateRefreshJWT(clientId string, key *rsa.PrivateKey) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
return token.SignedString(key)
}

// Returns true if the token is present and not expired
func IsTokenValid(token models.ZubeAccessToken) bool {
if token.AccessToken != "" {
isExp, _ := isAccessTokenExpired(token.AccessToken)
return !isExp
}

return false
}

// Returns true if the JWT is expired
func isAccessTokenExpired(accessToken string) (bool, error) {
token, _, err := new(jwt.Parser).ParseUnverified(accessToken, jwt.MapClaims{})

if err != nil {
log.Fatal(err)
return true, err
}

claims, ok := token.Claims.(jwt.MapClaims)

if !ok {
log.Fatalf("Can't convert token's claims to standard claims")
}

var expTime time.Time
now := time.Now()

switch exp := claims["exp"].(type) {
case float64:
expTime = time.Unix(int64(exp), 0)
case json.Number:
v, _ := exp.Int64()
expTime = time.Unix(v, 0)
}

isExpired := expTime.Unix() < now.Unix()

return isExpired, nil
}
36 changes: 16 additions & 20 deletions zube/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"

"github.com/platogo/zube-cli/zube/models"
"github.com/spf13/viper"
)

const (
Expand Down Expand Up @@ -78,46 +79,41 @@ type Client struct {
ClientId string // Your unique client ID
}

// Sets up a client with a profile, and caches it if needed
func NewClientWithProfile(profile *Profile) (*Client, error) {
client := NewClient(profile.ClientId)
// Creates and returns a Zube Client with an access token
// If the current access token is invalid, it is refreshes and saved to config
func NewClient() (*Client, error) {
client := &Client{
ClientId: viper.GetString("client_id"),
ZubeAccessToken: models.ZubeAccessToken{AccessToken: viper.GetString("access_token")},
}

if profile.IsTokenValid() {
client.AccessToken = profile.AccessToken
} else {
// Refresh client token and dump it to profile
if !IsTokenValid(client.ZubeAccessToken) {
privateKey, err := GetPrivateKey()

if err != nil {
log.Fatalln(err)
return client, err
}

profile.AccessToken, err = client.RefreshAccessToken(privateKey)
access_token, err := client.RefreshAccessToken(privateKey)

if err != nil {
log.Fatalln(err)
return client, err
}

ok := profile.SaveToConfig()

if ok != nil {
log.Fatal("Failed to save current configuration:", ok)
}
viper.Set("access_token", access_token)
viper.WriteConfig()
client.ZubeAccessToken.AccessToken = access_token
}

return client, nil
}

// Constructs a new client with only host and Client ID configured, enough to make an access token request.
func NewClient(clientId string) *Client {
func NewClientWithId(clientId string) *Client {
return &Client{Host: ZubeHost, ClientId: clientId}
}

// Like `NewClient`, but requires and access token ready to be used for API requests.
func NewClientWithAccessToken(clientId, accessToken string) *Client {
return &Client{Host: ZubeHost, ClientId: clientId, ZubeAccessToken: models.ZubeAccessToken{AccessToken: accessToken}}
}

// Fetch the access token JWT from Zube API and set it for the client. If it already exists, refresh it.
func (client *Client) RefreshAccessToken(key *rsa.PrivateKey) (string, error) {
refreshJWT, err := GenerateRefreshJWT(client.ClientId, key)
Expand Down
86 changes: 0 additions & 86 deletions zube/config.go

This file was deleted.

0 comments on commit 5b8b8c1

Please sign in to comment.