supabase-cli/internal/utils/access_token_test.go

205 lines
5.5 KiB
Go

package utils
import (
"os"
"testing"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/supabase/cli/internal/testing/apitest"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/utils/credentials"
"github.com/zalando/go-keyring"
)
func TestLoadToken(t *testing.T) {
keyring.MockInit()
token := string(apitest.RandomAccessToken(t))
t.Run("loads token from env var", func(t *testing.T) {
t.Setenv("SUPABASE_ACCESS_TOKEN", token)
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
loaded, err := LoadAccessTokenFS(fsys)
// Check error
assert.NoError(t, err)
assert.Equal(t, token, loaded)
})
t.Run("throws error on invalid token", func(t *testing.T) {
t.Setenv("SUPABASE_ACCESS_TOKEN", "invalid")
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
loaded, err := LoadAccessTokenFS(fsys)
// Check error
assert.ErrorIs(t, err, ErrInvalidToken)
assert.Empty(t, loaded)
})
t.Run("throws error on missing token", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
loaded, err := LoadAccessTokenFS(fsys)
// Check error
assert.ErrorIs(t, err, ErrMissingToken)
assert.Empty(t, loaded)
})
}
func TestLoadTokenFallback(t *testing.T) {
t.Run("fallback loads from file", func(t *testing.T) {
path, err := getAccessTokenPath()
assert.NoError(t, err)
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0600))
// Run test
token, err := fallbackLoadToken(fsys)
// Check error
assert.NoError(t, err)
assert.Empty(t, token)
})
t.Run("throws error on home dir failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
// Setup empty home directory
t.Setenv("HOME", "")
// Run test
token, err := fallbackLoadToken(fsys)
// Check error
assert.ErrorContains(t, err, "$HOME is not defined")
assert.Empty(t, token)
})
t.Run("throws error on read failure", func(t *testing.T) {
path, err := getAccessTokenPath()
assert.NoError(t, err)
// Setup in-memory fs
fsys := &fstest.OpenErrorFs{DenyPath: path}
// Run test
token, err := fallbackLoadToken(fsys)
// Check error
assert.ErrorContains(t, err, "permission denied")
assert.Empty(t, token)
})
}
func TestSaveToken(t *testing.T) {
keyring.MockInit()
token := string(apitest.RandomAccessToken(t))
t.Run("saves token to keyring", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
assert.NoError(t, SaveAccessToken(token, fsys))
// Validate saved token
saved, err := LoadAccessTokenFS(fsys)
assert.NoError(t, err)
assert.Equal(t, token, saved)
})
t.Run("throws error on invalid token", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
err := SaveAccessToken("invalid", fsys)
// Check error
assert.ErrorIs(t, err, ErrInvalidToken)
})
}
func TestSaveTokenFallback(t *testing.T) {
token := string(apitest.RandomAccessToken(t))
t.Run("fallback saves to file", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
assert.NoError(t, fallbackSaveToken(token, fsys))
// Validate saved token
path, err := getAccessTokenPath()
assert.NoError(t, err)
contents, err := afero.ReadFile(fsys, path)
assert.NoError(t, err)
assert.Equal(t, []byte(token), contents)
})
t.Run("throws error on home dir failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
// Setup empty home directory
t.Setenv("HOME", "")
// Run test
err := fallbackSaveToken(token, fsys)
// Check error
assert.ErrorContains(t, err, "$HOME is not defined")
})
t.Run("throws error on permission denied", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
// Run test
err := fallbackSaveToken(token, fsys)
// Check error
assert.ErrorContains(t, err, "operation not permitted")
})
t.Run("throws error on write failure", func(t *testing.T) {
home, err := os.UserHomeDir()
assert.NoError(t, err)
// Setup in-memory fs
fsys := &fstest.OpenErrorFs{DenyPath: home}
// Run test
err = fallbackSaveToken(token, fsys)
// Check error
assert.ErrorContains(t, err, "permission denied")
})
}
func TestDeleteToken(t *testing.T) {
t.Run("deletes both keyring and fallback", func(t *testing.T) {
token := string(apitest.RandomAccessToken(t))
require.NoError(t, credentials.StoreProvider.Set(AccessTokenKey, token))
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, fallbackSaveToken(token, fsys))
// Run test
err := DeleteAccessToken(fsys)
// Check error
assert.NoError(t, err)
_, err = credentials.StoreProvider.Get(AccessTokenKey)
assert.ErrorIs(t, err, keyring.ErrNotFound)
path, err := getAccessTokenPath()
assert.NoError(t, err)
exists, err := afero.Exists(fsys, path)
assert.NoError(t, err)
assert.False(t, exists)
})
t.Run("throws error if not logged in", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
err := DeleteAccessToken(fsys)
// Check error
assert.ErrorIs(t, err, ErrNotLoggedIn)
})
t.Run("throws error on home dir failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
// Setup empty home directory
t.Setenv("HOME", "")
// Run test
err := DeleteAccessToken(fsys)
// Check error
assert.ErrorContains(t, err, "$HOME is not defined")
})
}