Skip to content

Commit edb3d2d

Browse files
authored
feat: sc-240965/check current access token (#324)
Check if access token is set before logging in
1 parent f24a1ea commit edb3d2d

4 files changed

Lines changed: 90 additions & 7 deletions

File tree

cmd/config/config.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,7 @@ func getConfig() (config.ConfigFile, *viper.Viper, error) {
228228
return config.ConfigFile{}, nil, err
229229
}
230230

231-
data, err := os.ReadFile(v.ConfigFileUsed())
232-
if err != nil {
233-
return config.ConfigFile{}, nil, err
234-
}
235-
236-
var c config.ConfigFile
237-
err = yaml.Unmarshal([]byte(data), &c)
231+
c, err := config.NewConfigFromFile(v.ConfigFileUsed(), os.ReadFile)
238232
if err != nil {
239233
return config.ConfigFile{}, nil, err
240234
}

cmd/login/login.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
cmdAnalytics "github.com/launchdarkly/ldcli/cmd/analytics"
1111
"github.com/launchdarkly/ldcli/cmd/cliflags"
1212
"github.com/launchdarkly/ldcli/internal/analytics"
13+
"github.com/launchdarkly/ldcli/internal/config"
1314
"github.com/launchdarkly/ldcli/internal/login"
1415
"github.com/launchdarkly/ldcli/internal/output"
1516
)
@@ -54,6 +55,10 @@ func NewLoginCmd(
5455

5556
func run(client login.Client) func(*cobra.Command, []string) error {
5657
return func(cmd *cobra.Command, args []string) error {
58+
if ok, err := config.AccessTokenIsSet(viper.GetViper().ConfigFileUsed()); !ok {
59+
return err
60+
}
61+
5762
deviceAuthorization, err := login.FetchDeviceAuthorization(
5863
client,
5964
login.ClientID,

internal/config/config.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strconv"
88

99
"github.com/mitchellh/go-homedir"
10+
"gopkg.in/yaml.v3"
1011

1112
"github.com/launchdarkly/ldcli/cmd/cliflags"
1213
"github.com/launchdarkly/ldcli/internal/errors"
@@ -26,6 +27,23 @@ type ConfigFile struct {
2627
Project string `json:"project,omitempty" yaml:"project,omitempty"`
2728
}
2829

30+
type ReadFile func(name string) ([]byte, error)
31+
32+
func NewConfigFromFile(f string, readFile ReadFile) (ConfigFile, error) {
33+
data, err := readFile(f)
34+
if err != nil {
35+
return ConfigFile{}, errors.NewError("could not read config file")
36+
}
37+
38+
var c ConfigFile
39+
err = yaml.Unmarshal([]byte(data), &c)
40+
if err != nil {
41+
return ConfigFile{}, errors.NewError("config file is invalid yaml")
42+
}
43+
44+
return c, nil
45+
}
46+
2947
func NewConfig(rawConfig map[string]interface{}) (ConfigFile, error) {
3048
var (
3149
accessToken string
@@ -91,3 +109,15 @@ func GetConfigFile() string {
91109

92110
return filepath.Join(configFilePath, "config.yml")
93111
}
112+
113+
func AccessTokenIsSet(filename string) (bool, error) {
114+
config, err := NewConfigFromFile(filename, os.ReadFile)
115+
if err != nil {
116+
return false, err
117+
}
118+
if config.AccessToken != "" {
119+
return false, errors.NewError("Your access token is already set. Remove it from the config if you wish to reset it.")
120+
}
121+
122+
return true, nil
123+
}

internal/config/config_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,65 @@ import (
88

99
"github.com/stretchr/testify/assert"
1010
"github.com/stretchr/testify/require"
11+
"gopkg.in/yaml.v3"
1112

1213
"github.com/launchdarkly/ldcli/internal/config"
1314
"github.com/launchdarkly/ldcli/internal/resources"
1415
)
1516

17+
type mockReadFile struct {
18+
contents []byte
19+
successful bool
20+
}
21+
22+
func (m mockReadFile) readFile(name string) ([]byte, error) {
23+
if !m.successful {
24+
return nil, errors.New("an error")
25+
}
26+
27+
if m.contents != nil {
28+
return yaml.Marshal(m.contents)
29+
}
30+
31+
return yaml.Marshal(map[string]interface{}{
32+
"access-token": "test-access-token",
33+
})
34+
}
35+
36+
func TestNewConfigFromFile(t *testing.T) {
37+
t.Run("with valid input is a valid config", func(t *testing.T) {
38+
mock := mockReadFile{
39+
successful: true,
40+
}
41+
42+
c, err := config.NewConfigFromFile("test-config-file", mock.readFile)
43+
44+
require.NoError(t, err)
45+
assert.Equal(t, "test-access-token", c.AccessToken)
46+
})
47+
48+
t.Run("with invalid file is an error", func(t *testing.T) {
49+
mock := mockReadFile{
50+
successful: false,
51+
}
52+
53+
_, err := config.NewConfigFromFile("test-config-file", mock.readFile)
54+
55+
assert.EqualError(t, err, "could not read config file")
56+
})
57+
58+
t.Run("with invalid formatting in the file contents is an error", func(t *testing.T) {
59+
mock := mockReadFile{
60+
contents: []byte(`invalid`),
61+
successful: true,
62+
}
63+
64+
_, err := config.NewConfigFromFile("test-config-file", mock.readFile)
65+
66+
assert.EqualError(t, err, "config file is invalid yaml")
67+
})
68+
}
69+
1670
func TestNewConfig(t *testing.T) {
1771
t.Run("analytics-opt-out", func(t *testing.T) {
1872
tests := map[string]struct {

0 commit comments

Comments
 (0)