polycule-connect/polyculeconnect/services/backend/backend_test.go

216 lines
6.3 KiB
Go
Raw Permalink Normal View History

package backend_test
import (
"encoding/json"
"fmt"
"testing"
"git.faercol.me/faercol/polyculeconnect/polyculeconnect/connector"
"git.faercol.me/faercol/polyculeconnect/polyculeconnect/services/backend"
"github.com/dexidp/dex/storage"
"github.com/dexidp/dex/storage/memory"
logt "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
testDomain string = "https://test.domain.com"
testClientID string = "this_is_an_id"
testClientSecret string = "this_is_a_secret"
testRedirectURI string = "http://127.0.0.1:5000/callback"
testConnectorName string = "Test connector"
)
func generateConnector(id string) storage.Connector {
confJson := fmt.Sprintf(`{
"issuer": "%s",
"clientID": "%s",
"clientSecret": "%s",
"redirectURI": "%s"
}`, testDomain, testClientID, testClientSecret, testRedirectURI)
storageConfig := storage.Connector{
ID: id,
Name: testConnectorName,
Type: "oidc",
Config: []byte(confJson),
}
return storageConfig
}
func generateConfig(id string) backend.BackendConfig {
return backend.BackendConfig{
ID: id,
Name: testConnectorName,
Issuer: testDomain,
ClientID: testClientID,
ClientSecret: testClientSecret,
RedirectURI: testRedirectURI,
}
}
func checkStrInMap(t *testing.T, vals map[string]interface{}, key, expected string) {
rawVal, ok := vals[key]
require.Truef(t, ok, "missing key %s", key)
strVal, ok := rawVal.(string)
require.Truef(t, ok, "invalid string format %v", rawVal)
assert.Equal(t, expected, strVal, "unexpected value")
}
func initStorage(t *testing.T) storage.Storage {
logger, _ := logt.NewNullLogger()
s := memory.New(logger)
require.NoError(t, s.CreateConnector(connector.RefuseAllConnectorConfig))
require.NoError(t, s.CreateConnector(generateConnector("test0")))
require.NoError(t, s.CreateConnector(generateConnector("test1")))
return s
}
func TestBackendConfigFromConnector(t *testing.T) {
connector := generateConnector("test")
var bc backend.BackendConfig
require.NoError(t, bc.FromConnector(connector))
assert.Equal(t, testDomain, bc.Issuer)
assert.Equal(t, testClientID, bc.ClientID)
assert.Equal(t, testClientSecret, bc.ClientSecret)
assert.Equal(t, testRedirectURI, bc.RedirectURI)
assert.Equal(t, testConnectorName, bc.Name)
assert.Equal(t, "test", bc.ID)
}
func TestBackendConfigInvalidType(t *testing.T) {
connector := generateConnector("test")
connector.Type = "test"
var bc backend.BackendConfig
assert.ErrorIs(t, bc.FromConnector(connector), backend.ErrUnsupportedType)
}
func TestBackendConfigInvalidOIDCConfig(t *testing.T) {
connector := generateConnector("test")
connector.Config = []byte("toto")
var bc backend.BackendConfig
assert.ErrorContains(t, bc.FromConnector(connector), "invalid OIDC config")
}
func TestOIDCConfigFromBackendConfig(t *testing.T) {
conf := generateConfig("test")
oidcConf := conf.OIDC()
assert.Equal(t, testDomain, oidcConf.Issuer)
assert.Equal(t, testClientID, oidcConf.ClientID)
assert.Equal(t, testClientSecret, oidcConf.ClientSecret)
assert.Equal(t, testRedirectURI, oidcConf.RedirectURI)
}
func TestConnectorConfigFromBackendConfig(t *testing.T) {
conf := generateConfig("test")
con, err := conf.Storage()
require.NoError(t, err)
// The OIDC config is stored as JSON data, we just want the raw keys here
var oidcConf map[string]interface{}
require.NoError(t, json.Unmarshal(con.Config, &oidcConf))
assert.Equal(t, "oidc", con.Type)
assert.Equal(t, "test", con.ID)
assert.Equal(t, testConnectorName, con.Name)
checkStrInMap(t, oidcConf, "issuer", testDomain)
checkStrInMap(t, oidcConf, "clientID", testClientID)
checkStrInMap(t, oidcConf, "clientSecret", testClientSecret)
checkStrInMap(t, oidcConf, "redirectURI", testRedirectURI)
}
func TestListBackendsEmpty(t *testing.T) {
logger, _ := logt.NewNullLogger()
s := memory.New(logger)
// add the default refuse all connector, it should not be visible in the list
require.NoError(t, s.CreateConnector(connector.RefuseAllConnectorConfig))
srv := backend.New(s)
backends, err := srv.ListBackends() // empty list, and no error
require.NoError(t, err)
require.Len(t, backends, 0)
}
func TestListBackendsNotEmpty(t *testing.T) {
s := initStorage(t)
srv := backend.New(s)
backends, err := srv.ListBackends() // empty list, and no error
expectedIds := []string{"test0", "test1"}
require.NoError(t, err)
assert.Len(t, backends, 2)
for _, c := range backends {
assert.Contains(t, expectedIds, c.ID)
}
}
func TestGetBackend(t *testing.T) {
s := initStorage(t)
srv := backend.New(s)
t.Run("OK", func(t *testing.T) {
conf, err := srv.GetBackend("test0")
require.NoError(t, err)
assert.Equal(t, testDomain, conf.Issuer)
assert.Equal(t, testClientID, conf.ClientID)
assert.Equal(t, testClientSecret, conf.ClientSecret)
assert.Equal(t, testRedirectURI, conf.RedirectURI)
assert.Equal(t, testConnectorName, conf.Name)
assert.Equal(t, "test0", conf.ID)
})
t.Run("Not exist", func(t *testing.T) {
_, err := srv.GetBackend("toto")
assert.ErrorIs(t, err, storage.ErrNotFound)
})
t.Run("Invalid type", func(t *testing.T) {
_, err := srv.GetBackend("null") // null has a RefuseAll type, which is unsupported here
assert.ErrorIs(t, err, backend.ErrUnsupportedType)
})
}
func TestAddBackend(t *testing.T) {
s := initStorage(t)
srv := backend.New(s)
t.Run("OK", func(t *testing.T) {
conf := generateConfig("test_add")
require.NoError(t, srv.AddBackend(conf))
var parsedConf backend.BackendConfig
storageConf, err := s.GetConnector("test_add")
require.NoError(t, err)
require.NoError(t, parsedConf.FromConnector(storageConf))
assert.Equal(t, conf, parsedConf)
})
t.Run("Already exists", func(t *testing.T) {
require.ErrorIs(t, srv.AddBackend(generateConfig("test0")), storage.ErrAlreadyExists)
})
}
func TestRemoveBackend(t *testing.T) {
s := initStorage(t)
srv := backend.New(s)
t.Run("OK", func(t *testing.T) {
require.NoError(t, srv.AddBackend(generateConfig("to_remove")))
_, err := s.GetConnector("to_remove")
require.NoError(t, err) // no error means it's present
require.NoError(t, srv.RemoveBackend("to_remove"))
_, err = s.GetConnector("to_remove")
assert.ErrorIs(t, err, storage.ErrNotFound) // means it's been deleted
})
t.Run("No present", func(t *testing.T) {
require.ErrorIs(t, srv.RemoveBackend("toto"), storage.ErrNotFound)
})
}