diff --git a/auth/token.go b/auth/token.go index c6d80d0..5813743 100644 --- a/auth/token.go +++ b/auth/token.go @@ -3,14 +3,12 @@ package auth import ( "encoding/json" "fmt" + "github.com/cloudquery/cloudquery-api-go/config" "io" "net/http" "net/url" "os" - "strings" "time" - - "github.com/adrg/xdg" ) const ( @@ -18,6 +16,7 @@ const ( TokenBaseURL = "https://securetoken.googleapis.com" EnvVarCloudQueryAPIKey = "CLOUDQUERY_API_KEY" ExpiryBuffer = 60 * time.Second + tokenFilePath = "cloudquery/token" ) type tokenResponse struct { @@ -131,46 +130,15 @@ func parseToken(response []byte, tr *tokenResponse) error { // SaveRefreshToken saves the refresh token to the token file func SaveRefreshToken(refreshToken string) error { - tokenFilePath, err := xdg.DataFile("cloudquery/token") - if err != nil { - return fmt.Errorf("failed to get token file path: %w", err) - } - tokenFile, err := os.OpenFile(tokenFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return fmt.Errorf("failed to open token file %q for writing: %w", tokenFilePath, err) - } - defer func() { - if closeErr := tokenFile.Close(); closeErr != nil { - fmt.Printf("error closing token file: %v", closeErr) - } - }() - if _, err = tokenFile.WriteString(refreshToken); err != nil { - return fmt.Errorf("failed to write token to %q: %w", tokenFilePath, err) - } - return nil + return config.SaveDataString(tokenFilePath, refreshToken) } // ReadRefreshToken reads the refresh token from the token file func ReadRefreshToken() (string, error) { - tokenFilePath, err := xdg.DataFile("cloudquery/token") - if err != nil { - return "", fmt.Errorf("failed to get token file path: %w", err) - } - b, err := os.ReadFile(tokenFilePath) - if err != nil { - return "", fmt.Errorf("failed to read token file: %w", err) - } - return strings.TrimSpace(string(b)), nil + return config.ReadDataString(tokenFilePath) } // RemoveRefreshToken removes the token file func RemoveRefreshToken() error { - tokenFilePath, err := xdg.DataFile("cloudquery/token") - if err != nil { - return fmt.Errorf("failed to get token file path: %w", err) - } - if err := os.RemoveAll(tokenFilePath); err != nil { - return fmt.Errorf("failed to remove token file %q: %w", tokenFilePath, err) - } - return nil + return config.DeleteDataString(tokenFilePath) } diff --git a/config/config.go b/config/config.go index d2270ab..65bea4a 100644 --- a/config/config.go +++ b/config/config.go @@ -18,20 +18,12 @@ var configKeys = []string{ // SetConfigHome sets the configuration home directory - useful for testing func SetConfigHome(configDir string) error { - if err := os.Setenv("XDG_CONFIG_HOME", configDir); err != nil { - return fmt.Errorf("failed to set XDG_CONFIG_HOME: %w", err) - } - xdg.Reload() - return nil + return setXDGEnv("XDG_CONFIG_HOME", configDir) } // UnsetConfigHome unsets the configuration home directory returning to the default value func UnsetConfigHome() error { - if err := os.Unsetenv("XDG_CONFIG_HOME"); err != nil { - return fmt.Errorf("failed to unset XDG_CONFIG_HOME: %w", err) - } - xdg.Reload() - return nil + return unsetXDGEnv("XDG_CONFIG_HOME") } // GetValue reads the value of a config key from the config file @@ -106,3 +98,77 @@ func setValue(key string, val *string) error { } return nil } + +// SetDataHome sets the data home directory - useful for testing +func SetDataHome(dataHome string) error { + return setXDGEnv("XDG_DATA_HOME", dataHome) +} + +// UnsetDataHome unsets the data home directory returning to the default value +func UnsetDataHome() error { + return unsetXDGEnv("XDG_DATA_HOME") +} + +// SaveDataString saves a string to a file in the data home directory +func SaveDataString(relPath string, data string) error { + filePath, err := xdg.DataFile(relPath) + if err != nil { + return fmt.Errorf("failed to get token file path: %w", err) + } + file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return fmt.Errorf("failed to open file %q for writing: %w", filePath, err) + } + defer func() { + if closeErr := file.Close(); closeErr != nil { + fmt.Printf("error closing token file: %v", closeErr) + } + }() + if _, err = file.WriteString(data); err != nil { + return fmt.Errorf("failed to write data to %q: %w", filePath, err) + } + return nil +} + +// ReadDataString reads a string from a file in the data home directory +func ReadDataString(relPath string) (string, error) { + filePath, err := xdg.DataFile(relPath) + if err != nil { + return "", fmt.Errorf("failed to get file path: %w", err) + } + b, err := os.ReadFile(filePath) + if err != nil { + return "", fmt.Errorf("failed to read file: %w", err) + } + return strings.TrimSpace(string(b)), nil +} + +// DeleteDataString deletes a file in the data home directory +func DeleteDataString(relPath string) error { + filePath, err := xdg.DataFile(relPath) + if err != nil { + return fmt.Errorf("failed to get file path: %w", err) + } + if err := os.RemoveAll(filePath); err != nil { + return fmt.Errorf("failed to remove file %q: %w", filePath, err) + } + return nil +} + +func setXDGEnv(key, value string) error { + err := os.Setenv(key, value) + if err != nil { + return fmt.Errorf("failed to set %s: %w", key, err) + } + xdg.Reload() + return nil +} + +func unsetXDGEnv(key string) error { + err := os.Unsetenv(key) + if err != nil { + return fmt.Errorf("failed to unset %s: %w", key, err) + } + xdg.Reload() + return nil +} diff --git a/config/config_test.go b/config/config_test.go index 5705b9b..d637917 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -63,3 +63,27 @@ func TestSetConfigHome(t *testing.T) { // check that we are no longer set to the temporary directory r.NotEqual(configDir, xdg.ConfigHome) } + +func TestSetDataHome(t *testing.T) { + r := require.New(t) + configDir := t.TempDir() + + err := SetDataHome(configDir) + r.NoError(err) + + r.Equal(configDir, xdg.DataHome) + + err = SaveDataString("cloudquery/token", "my-token") + r.NoError(err) + + // check that the config file was created in the temporary directory, + // not somewhere else + _, err = os.Stat(path.Join(configDir, "cloudquery", "token")) + r.NoError(err) + + err = UnsetDataHome() + r.NoError(err) + + // check that we are no longer set to the temporary directory + r.NotEqual(configDir, xdg.DataHome) +}