Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/admin/organizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package admin
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -33,7 +33,7 @@ func OrganizationsCmd(imsConfig *ims.Config) *cobra.Command {
if err != nil {
return fmt.Errorf("error in get admin organizations cmd: %w", err)
}
output.PrintPrettyJSON(resp)
fmt.Println(pretty.JSON(resp))
return nil
},
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/admin/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package admin
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -31,7 +31,7 @@ func ProfileCmd(imsConfig *ims.Config) *cobra.Command {
if err != nil {
return fmt.Errorf("error in get admin profile cmd: %w", err)
}
output.PrintPrettyJSON(resp)
fmt.Println(pretty.JSON(resp))
return nil
},
}
Expand Down
5 changes: 3 additions & 2 deletions cmd/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ package cmd
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/spf13/cobra"
)
Expand All @@ -32,9 +33,9 @@ func decodeCmd(imsConfig *ims.Config) *cobra.Command {
return fmt.Errorf("error decoding the token: %w", err)
}

fmt.Println(decoded.Header)
fmt.Println(pretty.JSON(decoded.Header))
fmt.Println()
fmt.Println(decoded.Payload)
fmt.Println(pretty.JSON(decoded.Payload))

return nil
},
Expand Down
4 changes: 2 additions & 2 deletions cmd/organizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package cmd
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -33,7 +33,7 @@ func organizationsCmd(imsConfig *ims.Config) *cobra.Command {
if err != nil {
return fmt.Errorf("error in get organizations cmd: %w", err)
}
output.PrintPrettyJSON(resp)
fmt.Println(pretty.JSON(resp))
return nil
},
}
Expand Down
20 changes: 8 additions & 12 deletions output/output.go → cmd/pretty/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,19 @@
// OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.

package output
package pretty

import (
"bytes"
"encoding/json"
"fmt"
)

// PrintPrettyJSON prints a JSON string with indentation.
// If the input is not valid JSON, it prints the original string.
func PrintPrettyJSON(jsonStr string) {
var prettyBuf bytes.Buffer
err := json.Indent(&prettyBuf, []byte(jsonStr), "", " ")
if err != nil {
// Not valid JSON, print as-is
fmt.Println(jsonStr)
return
// JSON returns the input with JSON indentation applied.
// If the input is not valid JSON, it returns the original string.
func JSON(jsonStr string) string {
var buf bytes.Buffer
if err := json.Indent(&buf, []byte(jsonStr), "", " "); err != nil {
return jsonStr
}
fmt.Println(prettyBuf.String())
return buf.String()
}
44 changes: 8 additions & 36 deletions output/output_test.go → cmd/pretty/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,25 @@
// OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.

package output
package pretty

import (
"bytes"
"io"
"os"
"path/filepath"
"strings"
"testing"
)

// captureStdout captures the output of a function that writes to stdout.
func captureStdout(t *testing.T, fn func()) string {
t.Helper()
old := os.Stdout
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("failed to create pipe: %v", err)
}
os.Stdout = w

fn()

w.Close()
os.Stdout = old

var buf bytes.Buffer
if _, err := io.Copy(&buf, r); err != nil {
t.Fatalf("failed to read pipe: %v", err)
}
return buf.String()
}

// loadExpected reads the expected output from a golden file in testdata/.
func loadExpected(t *testing.T, filename string) string {
t.Helper()
data, err := os.ReadFile(filepath.Join("testdata", filename))
if err != nil {
t.Fatalf("failed to read golden file %s: %v", filename, err)
}
return string(data)
return strings.TrimSuffix(string(data), "\n")
}

func TestPrintPrettyJSON(t *testing.T) {
func TestJSON(t *testing.T) {
tests := []struct {
name string
input string
Expand All @@ -62,20 +38,16 @@ func TestPrintPrettyJSON(t *testing.T) {
{name: "empty object", input: `{}`, file: "empty_object.json"},
{name: "empty array", input: `[]`, file: "empty_array.json"},
{name: "nested objects", input: `{"a":{"b":{"c":1}}}`, file: "nested_objects.json"},
{name: "non-JSON is printed as-is", input: "this is not JSON", file: "non_json.txt"},
{name: "empty string is printed as-is", input: "", file: "empty_string.txt"},
{name: "non-JSON is returned as-is", input: "this is not JSON", file: "non_json.txt"},
{name: "empty string is returned as-is", input: "", file: "empty_string.txt"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
expected := loadExpected(t, tt.file)

got := captureStdout(t, func() {
PrintPrettyJSON(tt.input)
})

got := JSON(tt.input)
if got != expected {
t.Errorf("PrintPrettyJSON(%q)\ngot:\n%s\nexpected output is in testdata/%s", tt.input, got, tt.file)
t.Errorf("JSON(%q)\ngot:\n%s\nexpected:\n%s", tt.input, got, expected)
}
})
}
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions cmd/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package cmd
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -32,7 +32,7 @@ func profileCmd(imsConfig *ims.Config) *cobra.Command {
if err != nil {
return fmt.Errorf("error in get profile cmd: %w", err)
}
output.PrintPrettyJSON(resp)
fmt.Println(pretty.JSON(resp))
return nil
},
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/validate/access_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package validate
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -35,7 +35,7 @@ func AccessTokenCmd(imsConfig *ims.Config) *cobra.Command {
if !resp.Valid {
return fmt.Errorf("invalid token: %v", resp.Info)
}
output.PrintPrettyJSON(resp.Info)
fmt.Println(pretty.JSON(resp.Info))
return nil
},
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/validate/authorization_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package validate
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -35,7 +35,7 @@ func AuthzCodeCmd(imsConfig *ims.Config) *cobra.Command {
if !resp.Valid {
return fmt.Errorf("invalid token: %v", resp.Info)
}
output.PrintPrettyJSON(resp.Info)
fmt.Println(pretty.JSON(resp.Info))
return nil
},
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/validate/device_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package validate
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -35,7 +35,7 @@ func DeviceTokenCmd(imsConfig *ims.Config) *cobra.Command {
if !resp.Valid {
return fmt.Errorf("invalid token: %v", resp.Info)
}
output.PrintPrettyJSON(resp.Info)
fmt.Println(pretty.JSON(resp.Info))
return nil
},
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/validate/refresh_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package validate
import (
"fmt"

"github.com/adobe/imscli/cmd/pretty"
"github.com/adobe/imscli/ims"
"github.com/adobe/imscli/output"
"github.com/spf13/cobra"
)

Expand All @@ -35,7 +35,7 @@ func RefreshTokenCmd(imsConfig *ims.Config) *cobra.Command {
if !resp.Valid {
return fmt.Errorf("invalid token: %v", resp.Info)
}
output.PrintPrettyJSON(resp.Info)
fmt.Println(pretty.JSON(resp.Info))
return nil
},
}
Expand Down
36 changes: 7 additions & 29 deletions ims/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,15 @@
package ims

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
)

// DecodedToken represents the decoded parts of a JWT token.
type DecodedToken struct {
Header string
Payload string
Signature string
Header string
Payload string
}

func (i Config) validateDecodeTokenConfig() error {
Expand All @@ -44,40 +41,21 @@ func (i Config) DecodeToken() (*DecodedToken, error) {
return nil, fmt.Errorf("the JWT is not composed by 3 parts")
}

// Decode header and payload (not signature since it's binary)
decoded := &DecodedToken{
Signature: parts[2],
}
decoded := &DecodedToken{}

// Decode and prettify header
// Decode header
headerBytes, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil {
return nil, fmt.Errorf("error decoding token header: %w", err)
}
decoded.Header, err = prettyJSON(headerBytes)
if err != nil {
return nil, fmt.Errorf("error formatting token header: %w", err)
}
decoded.Header = string(headerBytes)

// Decode and prettify payload
// Decode payload
payloadBytes, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return nil, fmt.Errorf("error decoding token payload: %w", err)
}
decoded.Payload, err = prettyJSON(payloadBytes)
if err != nil {
return nil, fmt.Errorf("error formatting token payload: %w", err)
}
decoded.Payload = string(payloadBytes)

return decoded, nil
}

// prettyJSON formats JSON bytes with indentation.
func prettyJSON(data []byte) (string, error) {
var prettyBuf bytes.Buffer
err := json.Indent(&prettyBuf, data, "", " ")
if err != nil {
return "", err
}
return prettyBuf.String(), nil
}