Skip to content

Commit 3235143

Browse files
authored
feat: Allow configurable config home directory (#42)
1 parent 3b53c45 commit 3235143

File tree

3 files changed

+140
-37
lines changed

3 files changed

+140
-37
lines changed

auth/token.go

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,20 @@ package auth
33
import (
44
"encoding/json"
55
"fmt"
6+
"github.com/cloudquery/cloudquery-api-go/config"
67
"io"
78
"net/http"
89
"net/url"
910
"os"
10-
"strings"
1111
"time"
12-
13-
"github.com/adrg/xdg"
1412
)
1513

1614
const (
1715
FirebaseAPIKey = "AIzaSyCxsrwjABEF-dWLzUqmwiL-ct02cnG9GCs"
1816
TokenBaseURL = "https://securetoken.googleapis.com"
1917
EnvVarCloudQueryAPIKey = "CLOUDQUERY_API_KEY"
2018
ExpiryBuffer = 60 * time.Second
19+
tokenFilePath = "cloudquery/token"
2120
)
2221

2322
type tokenResponse struct {
@@ -131,46 +130,15 @@ func parseToken(response []byte, tr *tokenResponse) error {
131130

132131
// SaveRefreshToken saves the refresh token to the token file
133132
func SaveRefreshToken(refreshToken string) error {
134-
tokenFilePath, err := xdg.DataFile("cloudquery/token")
135-
if err != nil {
136-
return fmt.Errorf("failed to get token file path: %w", err)
137-
}
138-
tokenFile, err := os.OpenFile(tokenFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
139-
if err != nil {
140-
return fmt.Errorf("failed to open token file %q for writing: %w", tokenFilePath, err)
141-
}
142-
defer func() {
143-
if closeErr := tokenFile.Close(); closeErr != nil {
144-
fmt.Printf("error closing token file: %v", closeErr)
145-
}
146-
}()
147-
if _, err = tokenFile.WriteString(refreshToken); err != nil {
148-
return fmt.Errorf("failed to write token to %q: %w", tokenFilePath, err)
149-
}
150-
return nil
133+
return config.SaveDataString(tokenFilePath, refreshToken)
151134
}
152135

153136
// ReadRefreshToken reads the refresh token from the token file
154137
func ReadRefreshToken() (string, error) {
155-
tokenFilePath, err := xdg.DataFile("cloudquery/token")
156-
if err != nil {
157-
return "", fmt.Errorf("failed to get token file path: %w", err)
158-
}
159-
b, err := os.ReadFile(tokenFilePath)
160-
if err != nil {
161-
return "", fmt.Errorf("failed to read token file: %w", err)
162-
}
163-
return strings.TrimSpace(string(b)), nil
138+
return config.ReadDataString(tokenFilePath)
164139
}
165140

166141
// RemoveRefreshToken removes the token file
167142
func RemoveRefreshToken() error {
168-
tokenFilePath, err := xdg.DataFile("cloudquery/token")
169-
if err != nil {
170-
return fmt.Errorf("failed to get token file path: %w", err)
171-
}
172-
if err := os.RemoveAll(tokenFilePath); err != nil {
173-
return fmt.Errorf("failed to remove token file %q: %w", tokenFilePath, err)
174-
}
175-
return nil
143+
return config.DeleteDataString(tokenFilePath)
176144
}

config/config.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ var configKeys = []string{
1616
"team",
1717
}
1818

19+
// SetConfigHome sets the configuration home directory - useful for testing
20+
func SetConfigHome(configDir string) error {
21+
return setXDGEnv("XDG_CONFIG_HOME", configDir)
22+
}
23+
24+
// UnsetConfigHome unsets the configuration home directory returning to the default value
25+
func UnsetConfigHome() error {
26+
return unsetXDGEnv("XDG_CONFIG_HOME")
27+
}
28+
1929
// GetValue reads the value of a config key from the config file
2030
func GetValue(key string) (string, error) {
2131
if !slices.Contains(configKeys, key) {
@@ -88,3 +98,77 @@ func setValue(key string, val *string) error {
8898
}
8999
return nil
90100
}
101+
102+
// SetDataHome sets the data home directory - useful for testing
103+
func SetDataHome(dataHome string) error {
104+
return setXDGEnv("XDG_DATA_HOME", dataHome)
105+
}
106+
107+
// UnsetDataHome unsets the data home directory returning to the default value
108+
func UnsetDataHome() error {
109+
return unsetXDGEnv("XDG_DATA_HOME")
110+
}
111+
112+
// SaveDataString saves a string to a file in the data home directory
113+
func SaveDataString(relPath string, data string) error {
114+
filePath, err := xdg.DataFile(relPath)
115+
if err != nil {
116+
return fmt.Errorf("failed to get file path: %w", err)
117+
}
118+
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
119+
if err != nil {
120+
return fmt.Errorf("failed to open file %q for writing: %w", filePath, err)
121+
}
122+
defer func() {
123+
if closeErr := file.Close(); closeErr != nil {
124+
fmt.Printf("error closing file: %v", closeErr)
125+
}
126+
}()
127+
if _, err = file.WriteString(data); err != nil {
128+
return fmt.Errorf("failed to write data to %q: %w", filePath, err)
129+
}
130+
return nil
131+
}
132+
133+
// ReadDataString reads a string from a file in the data home directory
134+
func ReadDataString(relPath string) (string, error) {
135+
filePath, err := xdg.DataFile(relPath)
136+
if err != nil {
137+
return "", fmt.Errorf("failed to get file path: %w", err)
138+
}
139+
b, err := os.ReadFile(filePath)
140+
if err != nil {
141+
return "", fmt.Errorf("failed to read file: %w", err)
142+
}
143+
return strings.TrimSpace(string(b)), nil
144+
}
145+
146+
// DeleteDataString deletes a file in the data home directory
147+
func DeleteDataString(relPath string) error {
148+
filePath, err := xdg.DataFile(relPath)
149+
if err != nil {
150+
return fmt.Errorf("failed to get file path: %w", err)
151+
}
152+
if err := os.RemoveAll(filePath); err != nil {
153+
return fmt.Errorf("failed to remove file %q: %w", filePath, err)
154+
}
155+
return nil
156+
}
157+
158+
func setXDGEnv(key, value string) error {
159+
err := os.Setenv(key, value)
160+
if err != nil {
161+
return fmt.Errorf("failed to set %s: %w", key, err)
162+
}
163+
xdg.Reload()
164+
return nil
165+
}
166+
167+
func unsetXDGEnv(key string) error {
168+
err := os.Unsetenv(key)
169+
if err != nil {
170+
return fmt.Errorf("failed to unset %s: %w", key, err)
171+
}
172+
xdg.Reload()
173+
return nil
174+
}

config/config_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package config
22

33
import (
4+
"github.com/stretchr/testify/require"
5+
"os"
6+
"path"
47
"testing"
58

69
"github.com/adrg/xdg"
@@ -36,3 +39,51 @@ func TestSetGetValue(t *testing.T) {
3639
t.Fatalf("expected %q, got %q", "", got)
3740
}
3841
}
42+
43+
func TestSetConfigHome(t *testing.T) {
44+
r := require.New(t)
45+
configDir := t.TempDir()
46+
47+
err := SetConfigHome(configDir)
48+
r.NoError(err)
49+
50+
r.Equal(configDir, xdg.ConfigHome)
51+
52+
err = SetValue("team", "set-config-test-value")
53+
r.NoError(err)
54+
55+
// check that the config file was created in the temporary directory,
56+
// not somewhere else
57+
_, err = os.Stat(path.Join(configDir, "cloudquery", "config.json"))
58+
r.NoError(err)
59+
60+
err = UnsetConfigHome()
61+
r.NoError(err)
62+
63+
// check that we are no longer set to the temporary directory
64+
r.NotEqual(configDir, xdg.ConfigHome)
65+
}
66+
67+
func TestSetDataHome(t *testing.T) {
68+
r := require.New(t)
69+
configDir := t.TempDir()
70+
71+
err := SetDataHome(configDir)
72+
r.NoError(err)
73+
74+
r.Equal(configDir, xdg.DataHome)
75+
76+
err = SaveDataString("cloudquery/token", "my-token")
77+
r.NoError(err)
78+
79+
// check that the config file was created in the temporary directory,
80+
// not somewhere else
81+
_, err = os.Stat(path.Join(configDir, "cloudquery", "token"))
82+
r.NoError(err)
83+
84+
err = UnsetDataHome()
85+
r.NoError(err)
86+
87+
// check that we are no longer set to the temporary directory
88+
r.NotEqual(configDir, xdg.DataHome)
89+
}

0 commit comments

Comments
 (0)