Path: blob/main/components/gitpod-db/go/oidc_client_config_test.go
2498 views
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package db_test56import (7"context"8"testing"910db "github.com/gitpod-io/gitpod/components/gitpod-db/go"11"github.com/gitpod-io/gitpod/components/gitpod-db/go/dbtest"12"github.com/google/uuid"13"github.com/stretchr/testify/require"14)1516func TestCreateOIDCClientConfig_Create(t *testing.T) {17conn := dbtest.ConnectForTests(t)18created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{})[0]1920retrieved, err := db.GetOIDCClientConfig(context.Background(), conn, created.ID)21require.NoError(t, err)22require.Equal(t, created, retrieved)23}2425func TestListOIDCClientConfigsForOrganization(t *testing.T) {26ctx := context.Background()27conn := dbtest.ConnectForTests(t)2829orgA, orgB := uuid.New(), uuid.New()3031dbtest.CreateOIDCClientConfigs(t, conn,32dbtest.NewOIDCClientConfig(t, db.OIDCClientConfig{33OrganizationID: orgA,34}),35dbtest.NewOIDCClientConfig(t, db.OIDCClientConfig{36OrganizationID: orgA,37}),38dbtest.NewOIDCClientConfig(t, db.OIDCClientConfig{39OrganizationID: orgB,40}),41)4243configsForOrgA, err := db.ListOIDCClientConfigsForOrganization(ctx, conn, orgA)44require.NoError(t, err)45require.Len(t, configsForOrgA, 2)4647configsForOrgB, err := db.ListOIDCClientConfigsForOrganization(ctx, conn, orgB)48require.NoError(t, err)49require.Len(t, configsForOrgB, 1)5051configsForRandomOrg, err := db.ListOIDCClientConfigsForOrganization(ctx, conn, uuid.New())52require.NoError(t, err)53require.Len(t, configsForRandomOrg, 0)54}5556func TestDeleteOIDCClientConfig(t *testing.T) {5758t.Run("returns not found, when record does not exist", func(t *testing.T) {59conn := dbtest.ConnectForTests(t)60orgID := uuid.New()6162err := db.DeleteOIDCClientConfig(context.Background(), conn, uuid.New(), orgID)63require.Error(t, err)64require.ErrorIs(t, err, db.ErrorNotFound)65})6667t.Run("marks record deleted", func(t *testing.T) {68conn := dbtest.ConnectForTests(t)69orgID := uuid.New()7071created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{72OrganizationID: orgID,73})[0]7475err := db.DeleteOIDCClientConfig(context.Background(), conn, created.ID, created.OrganizationID)76require.NoError(t, err)7778// Delete only sets the `deleted` field, verify that's true79var retrieved db.OIDCClientConfig80tx := conn.Where("id = ?", created.ID).Where("deleted = 1").First(&retrieved)81require.NoError(t, tx.Error)82})8384}8586func TestGetOIDCClientConfigForOrganization(t *testing.T) {8788t.Run("not found when config does not exist", func(t *testing.T) {89conn := dbtest.ConnectForTests(t)9091_, err := db.GetOIDCClientConfigForOrganization(context.Background(), conn, uuid.New(), uuid.New())92require.Error(t, err)93require.ErrorIs(t, err, db.ErrorNotFound)94})9596t.Run("retrieves config which exists", func(t *testing.T) {97conn := dbtest.ConnectForTests(t)9899orgID := uuid.New()100101created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{102OrganizationID: orgID,103})[0]104105retrieved, err := db.GetOIDCClientConfigForOrganization(context.Background(), conn, created.ID, created.OrganizationID)106require.NoError(t, err)107108require.Equal(t, created, retrieved)109})110111}112113func TestGetActiveOIDCClientConfigByOrgSlug(t *testing.T) {114115t.Run("not found when config does not exist", func(t *testing.T) {116conn := dbtest.ConnectForTests(t)117118_, err := db.GetActiveOIDCClientConfigByOrgSlug(context.Background(), conn, "non-existing-org")119require.Error(t, err)120require.ErrorIs(t, err, db.ErrorNotFound)121})122123t.Run("retrieves config which exists", func(t *testing.T) {124conn := dbtest.ConnectForTests(t)125126// create a single team127team := dbtest.CreateOrganizations(t, conn, db.Organization{})[0]128129created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{130OrganizationID: team.ID,131Active: true,132})[0]133134retrieved, err := db.GetActiveOIDCClientConfigByOrgSlug(context.Background(), conn, team.Slug)135require.NoError(t, err)136137require.Equal(t, created, retrieved)138})139140t.Run("retrieves single active config", func(t *testing.T) {141conn := dbtest.ConnectForTests(t)142143// create a single team144team := dbtest.CreateOrganizations(t, conn, db.Organization{})[0]145146// create multiple147activeConfigID := uuid.New()148configs := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{149ID: uuid.New(),150OrganizationID: team.ID,151Active: false,152}, db.OIDCClientConfig{153ID: activeConfigID,154OrganizationID: team.ID,155Active: true,156}, db.OIDCClientConfig{157ID: uuid.New(),158OrganizationID: team.ID,159Active: false,160})161require.Len(t, configs, 3)162163retrieved, err := db.GetActiveOIDCClientConfigByOrgSlug(context.Background(), conn, team.Slug)164require.NoError(t, err)165166require.Equal(t, activeConfigID, retrieved.ID)167168})169170}171172func TestActivateClientConfig(t *testing.T) {173174t.Run("not found when config does not exist", func(t *testing.T) {175conn := dbtest.ConnectForTests(t)176177err := db.SetClientConfigActiviation(context.Background(), conn, uuid.New(), true)178require.Error(t, err)179require.ErrorIs(t, err, db.ErrorNotFound)180})181182t.Run("config which exists is marked as active", func(t *testing.T) {183conn := dbtest.ConnectForTests(t)184185config := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{186OrganizationID: uuid.New(),187Active: false,188})[0]189configID := config.ID190191config, err := db.GetOIDCClientConfig(context.Background(), conn, configID)192require.NoError(t, err)193require.Equal(t, false, config.Active)194195err = db.SetClientConfigActiviation(context.Background(), conn, configID, true)196require.NoError(t, err)197198config2, err := db.GetOIDCClientConfig(context.Background(), conn, configID)199require.NoError(t, err)200require.Equal(t, true, config2.Active)201202err = db.SetClientConfigActiviation(context.Background(), conn, configID, true)203require.NoError(t, err)204})205206t.Run("config activation of config de-activates previous active one", func(t *testing.T) {207conn := dbtest.ConnectForTests(t)208209organizationId := uuid.New()210configs := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{211OrganizationID: organizationId,212Active: false,213}, db.OIDCClientConfig{214OrganizationID: organizationId,215Active: false,216})217config1 := configs[0]218config2 := configs[1]219220// activate first221err := db.SetClientConfigActiviation(context.Background(), conn, config1.ID, true)222require.NoError(t, err)223224config1, err = db.GetOIDCClientConfig(context.Background(), conn, config1.ID)225require.NoError(t, err)226require.Equal(t, true, config1.Active, "failed to activate config1")227228// activate second229err = db.SetClientConfigActiviation(context.Background(), conn, config2.ID, true)230require.NoError(t, err)231232config2, err = db.GetOIDCClientConfig(context.Background(), conn, config2.ID)233require.NoError(t, err)234require.Equal(t, true, config2.Active, "failed to activate config2")235236config1, err = db.GetOIDCClientConfig(context.Background(), conn, config1.ID)237require.NoError(t, err)238require.Equal(t, false, config1.Active, "failed to de-activate config1")239})240241}242243func TestUpdateOIDCSpec(t *testing.T) {244245t.Run("no existing client config exists", func(t *testing.T) {246conn := dbtest.ConnectForTests(t)247cipher, _ := dbtest.GetTestCipher(t)248249err := db.UpdateOIDCClientConfig(context.Background(), conn, cipher, db.OIDCClientConfig{250ID: uuid.New(),251}, nil)252require.Error(t, err)253require.ErrorIs(t, err, db.ErrorNotFound)254})255256t.Run("no existing client config exists with spec update", func(t *testing.T) {257conn := dbtest.ConnectForTests(t)258cipher, _ := dbtest.GetTestCipher(t)259260err := db.UpdateOIDCClientConfig(context.Background(), conn, cipher, db.OIDCClientConfig{261ID: uuid.New(),262}, &db.OIDCSpec{})263require.Error(t, err)264require.ErrorIs(t, err, db.ErrorNotFound)265})266267t.Run("partially updates issuer, active, client id and client secret", func(t *testing.T) {268conn := dbtest.ConnectForTests(t)269cipher, _ := dbtest.GetTestCipher(t)270271created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{})[0]272273err := db.UpdateOIDCClientConfig(context.Background(), conn, cipher, db.OIDCClientConfig{274ID: created.ID,275Active: true,276Issuer: "some-new-issuer",277}, &db.OIDCSpec{278ClientID: "my-new-client-id",279ClientSecret: "new-client-secret",280})281require.NoError(t, err)282283retrieved, err := db.GetOIDCClientConfig(context.Background(), conn, created.ID)284require.NoError(t, err)285286decrypted, err := retrieved.Data.Decrypt(cipher)287require.NoError(t, err)288require.Equal(t, "my-new-client-id", decrypted.ClientID)289require.Equal(t, "new-client-secret", decrypted.ClientSecret)290require.True(t, retrieved.Active)291require.Equal(t, "some-new-issuer", retrieved.Issuer)292})293294t.Run("partially updates redirect url and scopes", func(t *testing.T) {295conn := dbtest.ConnectForTests(t)296cipher, _ := dbtest.GetTestCipher(t)297298created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{})[0]299300err := db.UpdateOIDCClientConfig(context.Background(), conn, cipher, db.OIDCClientConfig{301ID: created.ID,302}, &db.OIDCSpec{303RedirectURL: "new-url",304Scopes: []string{"hello"},305})306require.NoError(t, err)307308retrieved, err := db.GetOIDCClientConfig(context.Background(), conn, created.ID)309require.NoError(t, err)310311decrypted, err := retrieved.Data.Decrypt(cipher)312require.NoError(t, err)313require.Equal(t, "new-url", decrypted.RedirectURL)314require.Equal(t, []string{"hello"}, decrypted.Scopes)315})316317t.Run("partially updates all spec fields", func(t *testing.T) {318conn := dbtest.ConnectForTests(t)319cipher, _ := dbtest.GetTestCipher(t)320321created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{})[0]322323updateSpec := db.OIDCSpec{324RedirectURL: "new-url",325ClientID: "my-new-client-id",326ClientSecret: "new-client-secret",327Scopes: []string{"hello"},328}329330err := db.UpdateOIDCClientConfig(context.Background(), conn, cipher, db.OIDCClientConfig{331ID: created.ID,332}, &updateSpec)333require.NoError(t, err)334335retrieved, err := db.GetOIDCClientConfig(context.Background(), conn, created.ID)336require.NoError(t, err)337338decrypted, err := retrieved.Data.Decrypt(cipher)339require.NoError(t, err)340require.Equal(t, updateSpec, decrypted)341})342343t.Run("updates should unverify entries", func(t *testing.T) {344conn := dbtest.ConnectForTests(t)345cipher, _ := dbtest.GetTestCipher(t)346347created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{348Verified: db.BoolPointer(true),349})[0]350351updateSpec := db.OIDCSpec{352ClientSecret: "new-client-secret",353}354355err := db.UpdateOIDCClientConfig(context.Background(), conn, cipher, db.OIDCClientConfig{356ID: created.ID,357}, &updateSpec)358require.NoError(t, err)359360retrieved, err := db.GetOIDCClientConfig(context.Background(), conn, created.ID)361require.NoError(t, err)362require.NotEqual(t, created.Verified, retrieved.Verified)363})364365}366367368