Files
upstream-ory-kratos/persistence/sql/identity/persister_identity_test.go
upstream-mirror c60cc7ca75
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
2026-09-15 21:19:12 +05:00

123 lines
4.4 KiB
Go

// Copyright © 2026 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package identity_test
// Since:
// - This is a separate test package
// - Go creates one executable per test package
// - Go global variables are isolated per process (i.e. executable)
// - This test uses its own database
// , it means that this test is independent from the others and cannot interfere with them.
// We do not need to clear the global maps at the start of the test: they are still pristine (unset).
import (
"fmt"
"strings"
"testing"
"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
id "github.com/ory/kratos/identity"
"github.com/ory/kratos/persistence/sql/identity"
"github.com/ory/kratos/pkg"
"github.com/ory/kratos/pkg/testhelpers"
"github.com/ory/kratos/x"
"github.com/ory/x/dbal"
"github.com/ory/x/sqlxx"
)
// TestCreateIdentities_WritesExtraColumns verifies that WithExtraColumns is
// forwarded from CreateIdentities down to the batch INSERT.
func TestCreateIdentities_WritesExtraColumns(t *testing.T) {
_, reg := pkg.NewRegistryDefaultWithDSN(t, dbal.NewSQLiteTestDatabase(t))
_, p := testhelpers.NewNetwork(t, t.Context(), reg.Persister())
require.NoError(t,
p.GetConnection(t.Context()).RawQuery(`ALTER TABLE identities ADD COLUMN extra_foo TEXT`).Exec(),
)
ctx := testhelpers.WithDefaultIdentitySchemaFromRaw(t.Context(), []byte(`{"$id":"test","type":"object"}`))
ident := id.NewIdentity("")
require.NoError(t, p.CreateIdentities(ctx, []*id.Identity{ident},
id.WithExtraColumns([]id.ExtraColumn{{K: "extra_foo", V: "bar"}}),
))
var got string
require.NoError(t,
p.GetConnection(t.Context()).RawQuery(
`SELECT extra_foo FROM identities WHERE id = ?`, ident.ID,
).First(&got),
)
assert.Equal(t, "bar", got)
}
func TestNonStandardCredentialTypes(t *testing.T) {
_, reg := pkg.NewRegistryDefaultWithDSN(t, dbal.NewSQLiteTestDatabase(t))
_, p := testhelpers.NewNetwork(t, t.Context(), reg.Persister())
// Replace the content of the table with custom UUIDs. This relies on the
// process-global credential-types cache being pristine, which the header
// comment's package isolation guarantees — no other test in this package
// touches the cache first.
{
require.NoError(t, p.GetConnection(t.Context()).RawQuery(`DELETE FROM identity_credential_types`, x.NewUUID()).Exec())
// Test the case of empty credentials in the database, so that we can exercise the case of loading credentials failing,
// and then subsequent loads succeed, and the service does not get suck.
_, err := identity.FindIdentityCredentialsTypeByName(p.GetConnection(t.Context()), id.CredentialsTypeOIDC)
require.Error(t, err)
// Now fill the table with non-standard UUIDs.
q := strings.Builder{}
q.WriteString(`INSERT INTO identity_credential_types (id, name) VALUES `)
for i, ct := range id.AllCredentialTypes {
fmt.Fprintf(&q, `('%s', '%s')`, x.NewUUID(), ct)
if i < len(id.AllCredentialTypes)-1 {
q.WriteRune(',')
}
}
require.NoError(t, p.GetConnection(t.Context()).RawQuery(q.String()).Exec())
}
// Valid credential types are found.
for _, ct := range id.AllCredentialTypes {
t.Run("type="+ct.String(), func(t *testing.T) {
id, err := identity.FindIdentityCredentialsTypeByName(p.GetConnection(t.Context()), ct)
require.NoError(t, err)
require.NotEqual(t, uuid.Nil, id)
name, err := identity.FindIdentityCredentialsTypeByID(p.GetConnection(t.Context()), id)
require.NoError(t, err)
assert.Equal(t, ct, name)
})
}
// Invalid credential types are not found.
_, err := identity.FindIdentityCredentialsTypeByName(p.GetConnection(t.Context()), "unknown")
require.Error(t, err)
_, err = identity.FindIdentityCredentialsTypeByID(p.GetConnection(t.Context()), x.NewUUID())
require.Error(t, err)
// Create an identity and find it by credential identifier.
ctx := testhelpers.WithDefaultIdentitySchemaFromRaw(t.Context(), []byte(`{"$id":"test","type":"object"}`))
email := "test-" + x.NewUUID().String() + "@example.com"
i := id.NewIdentity("")
i.SetCredentials(id.CredentialsTypePassword, id.Credentials{
Type: id.CredentialsTypePassword,
Identifiers: []string{email},
Config: sqlxx.JSONRawMessage(`{}`),
})
require.NoError(t, p.CreateIdentity(ctx, i))
actualIdentity, actualCreds, err := p.FindByCredentialsIdentifier(ctx, id.CredentialsTypePassword, email)
require.NoError(t, err)
assert.Equal(t, i.ID, actualIdentity.ID)
assert.Equal(t, []string{email}, actualCreds.Identifiers)
}