Skip to content

Commit 46b92d2

Browse files
committed
Refactor secrets, info, and logs commands for consistency and robustness
1 parent 416581c commit 46b92d2

11 files changed

Lines changed: 122 additions & 174 deletions

File tree

cmd/info/info.go

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,56 @@ import (
55
"fmt"
66
"io"
77
"os"
8-
"strings"
98

109
"github.com/kloudkit/ws-cli/internals/config"
10+
internalIO "github.com/kloudkit/ws-cli/internals/io"
1111
"github.com/kloudkit/ws-cli/internals/styles"
1212
"github.com/spf13/cobra"
1313
)
1414

15-
func readJsonFile() map[string]any {
16-
var content map[string]any
17-
18-
data, _ := os.ReadFile(config.DefaultManifestPath)
19-
20-
_ = json.Unmarshal(data, &content)
21-
22-
return content
15+
type Manifest struct {
16+
Version string `json:"version"`
17+
VSCode struct {
18+
Version string `json:"version"`
19+
} `json:"vscode"`
2320
}
2421

25-
func readJson(content map[string]any, key string) string {
26-
keys := strings.Split(key, ".")
27-
var value any = content
28-
29-
for _, k := range keys {
30-
m, ok := value.(map[string]any)
31-
if !ok {
32-
return ""
33-
}
22+
func readManifest() (*Manifest, error) {
23+
if !internalIO.FileExists(config.DefaultManifestPath) {
24+
return nil, fmt.Errorf("manifest not found at %s", config.DefaultManifestPath)
25+
}
3426

35-
value = m[k]
27+
data, err := os.ReadFile(config.DefaultManifestPath)
28+
if err != nil {
29+
return nil, fmt.Errorf("failed to read manifest: %w", err)
3630
}
3731

38-
if str, ok := value.(string); ok {
39-
return str
32+
var m Manifest
33+
if err := json.Unmarshal(data, &m); err != nil {
34+
return nil, fmt.Errorf("failed to parse manifest: %w", err)
4035
}
4136

42-
return fmt.Sprintf("%v", value)
37+
return &m, nil
4338
}
4439

4540
func showVersion(writer io.Writer) {
46-
content := readJsonFile()
41+
manifest, err := readManifest()
42+
if err != nil {
43+
styles.PrintWarning(writer, fmt.Sprintf("Could not read workspace version: %v", err))
44+
fmt.Fprintf(writer, "%s\n", styles.Title().Render("Versions"))
45+
t := styles.Table().Rows(
46+
[]string{"ws-cli", Version},
47+
)
48+
fmt.Fprintln(writer, t.Render())
49+
return
50+
}
4751

4852
fmt.Fprintf(writer, "%s\n", styles.Title().Render("Versions"))
4953

5054
t := styles.Table().Rows(
51-
[]string{"workspace", readJson(content, "version")},
55+
[]string{"workspace", manifest.Version},
5256
[]string{"ws-cli", Version},
53-
[]string{"VSCode", readJson(content, "vscode.version")},
57+
[]string{"VSCode", manifest.VSCode.Version},
5458
)
5559

5660
fmt.Fprintln(writer, t.Render())

cmd/logs/logs.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package logs
22

33
import (
44
"fmt"
5-
"os"
65

76
"github.com/kloudkit/ws-cli/internals/logger"
87
"github.com/kloudkit/ws-cli/internals/styles"
@@ -28,13 +27,13 @@ func execute(cmd *cobra.Command, args []string) error {
2827
{"warn", "Warning messages"},
2928
{"error", "Error messages only"},
3029
})
31-
os.Exit(1)
30+
return fmt.Errorf("invalid log level")
3231
}
3332

3433
reader, err := logger.NewReader(tail, level)
3534
if err != nil {
3635
styles.PrintError(cmd.ErrOrStderr(), fmt.Sprintf("Failed to initialize log reader: %s", err))
37-
os.Exit(1)
36+
return err
3837
}
3938

4039
if follow {
@@ -45,7 +44,7 @@ func execute(cmd *cobra.Command, args []string) error {
4544

4645
if err != nil {
4746
styles.PrintError(cmd.ErrOrStderr(), fmt.Sprintf("Error reading logs: %s", err))
48-
os.Exit(1)
47+
return err
4948
}
5049

5150
return nil

cmd/secrets/encrypt.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,3 @@ var encryptCmd = &cobra.Command{
3737
return handleOutput(cmd, cfg, encrypted, "Encrypted Value", "Secret encrypted successfully", true)
3838
},
3939
}
40-
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
package generate
1+
package secrets
22

33
import "github.com/spf13/cobra"
44

5-
var GenerateCmd = &cobra.Command{
5+
var generateCmd = &cobra.Command{
66
Use: "generate",
77
Short: "Generate master keys or login password hashes",
88
}
99

1010
func init() {
11-
GenerateCmd.AddCommand(masterCmd, loginCmd)
11+
generateCmd.AddCommand(masterCmd, loginCmd)
1212
}

cmd/secrets/generate/helpers.go

Lines changed: 0 additions & 103 deletions
This file was deleted.

cmd/secrets/generate/login.go

Lines changed: 0 additions & 15 deletions
This file was deleted.

cmd/secrets/generate/master.go

Lines changed: 0 additions & 20 deletions
This file was deleted.

cmd/secrets/login.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package secrets
2+
3+
import (
4+
"fmt"
5+
"io"
6+
7+
internalIO "github.com/kloudkit/ws-cli/internals/io"
8+
internalSecrets "github.com/kloudkit/ws-cli/internals/secrets"
9+
"github.com/kloudkit/ws-cli/internals/styles"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
var loginCmd = &cobra.Command{
14+
Use: "login",
15+
Short: "Generate a workspace password hash for authentication",
16+
Args: cobra.NoArgs,
17+
RunE: func(cmd *cobra.Command, args []string) error {
18+
cfg := getOutputConfig(cmd)
19+
return generateLoginHash(cmd, cfg)
20+
},
21+
}
22+
23+
func generateLoginHash(cmd *cobra.Command, cfg outputConfig) error {
24+
password, err := internalIO.ReadPasswordFromReader(cmd.InOrStdin())
25+
if err != nil {
26+
return err
27+
}
28+
29+
hash, err := internalSecrets.HashPasswordForWorkspace(password)
30+
if err != nil {
31+
return err
32+
}
33+
34+
return handleCustomOutput(cmd, cfg, hash, "✓ Password hash written to "+cfg.file, func(out io.Writer) {
35+
fmt.Fprintf(out, "%s\n", styles.Header().Render("Workspace Password Hash"))
36+
fmt.Fprintf(out, " %s\n", styles.Code().Render(hash))
37+
fmt.Fprintf(out, "%s\n", styles.Muted().Render("💡 Use this hash for WS_AUTH_PASSWORD_HASHED"))
38+
})
39+
}

cmd/secrets/master.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package secrets
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/base64"
6+
"errors"
7+
"fmt"
8+
"io"
9+
10+
"github.com/kloudkit/ws-cli/internals/styles"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
var masterCmd = &cobra.Command{
15+
Use: "master",
16+
Short: "Generate a cryptographically secure master key",
17+
Args: cobra.NoArgs,
18+
RunE: func(cmd *cobra.Command, args []string) error {
19+
cfg := getOutputConfig(cmd)
20+
keyLength, _ := cmd.Flags().GetInt("length")
21+
return generateMasterKey(cmd, cfg, keyLength)
22+
},
23+
}
24+
25+
func init() {
26+
masterCmd.Flags().Int("length", 32, "Key length in bytes")
27+
}
28+
29+
func generateMasterKey(cmd *cobra.Command, cfg outputConfig, keyLength int) error {
30+
if keyLength <= 0 {
31+
return errors.New("invalid key length")
32+
}
33+
34+
key := make([]byte, keyLength)
35+
if _, err := rand.Read(key); err != nil {
36+
return fmt.Errorf("failed to generate key: %w", err)
37+
}
38+
39+
encodedKey := base64.StdEncoding.EncodeToString(key)
40+
41+
return handleCustomOutput(cmd, cfg, encodedKey, "✓ Master key written to "+cfg.file, func(out io.Writer) {
42+
fmt.Fprintf(out, "%s\n", styles.Header().Render("Master Key"))
43+
fmt.Fprintf(out, " %s\n", styles.Code().Render(encodedKey))
44+
fmt.Fprintf(out, "%s\n", styles.Muted().Render("💡 Store this key securely - you'll need it to encrypt/decrypt secrets"))
45+
})
46+
}

cmd/secrets/secrets.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package secrets
22

33
import (
4-
"github.com/kloudkit/ws-cli/cmd/secrets/generate"
54
"github.com/spf13/cobra"
65
)
76

@@ -17,5 +16,5 @@ func init() {
1716
SecretsCmd.PersistentFlags().Bool("force", false, "Overwrite existing files")
1817
SecretsCmd.PersistentFlags().Bool("raw", false, "Output without styling")
1918

20-
SecretsCmd.AddCommand(encryptCmd, decryptCmd, generate.GenerateCmd, vaultCmd)
19+
SecretsCmd.AddCommand(encryptCmd, decryptCmd, generateCmd, vaultCmd)
2120
}

0 commit comments

Comments
 (0)