snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
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

This commit is contained in:
upstream-mirror
2026-09-15 21:19:12 +05:00
commit c60cc7ca75
8092 changed files with 394160 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package sessiontokenexchange
import (
"context"
"time"
"github.com/gofrs/uuid"
)
type Codes struct {
InitCode string
ReturnToCode string
}
type Exchanger struct {
ID uuid.UUID `db:"id"`
NID uuid.UUID `db:"nid"`
FlowID uuid.UUID `db:"flow_id"`
SessionID uuid.NullUUID `db:"session_id"`
InitCode string `db:"init_code"`
ReturnToCode string `db:"return_to_code"`
// CreatedAt is a helper struct field for gobuffalo.pop.
CreatedAt time.Time `db:"created_at"`
// UpdatedAt is a helper struct field for gobuffalo.pop.
UpdatedAt time.Time `db:"updated_at"`
}
func (Exchanger) TableName() string { return "session_token_exchanges" }
type (
Persister interface {
CreateSessionTokenExchanger(ctx context.Context, flowID uuid.UUID) (e *Exchanger, err error)
GetExchangerFromCode(ctx context.Context, initCode string, returnToCode string) (*Exchanger, error)
GetExchangerFromCodeAllowPending(ctx context.Context, initCode string, returnToCode string) (*Exchanger, error)
UpdateSessionOnExchanger(ctx context.Context, flowID uuid.UUID, sessionID uuid.UUID) error
CodeForFlow(ctx context.Context, flowID uuid.UUID) (codes *Codes, found bool, err error)
MoveToNewFlow(ctx context.Context, oldFlow, newFlow uuid.UUID) error
DeleteExpiredExchangers(context.Context, time.Time, int) error
}
PersistenceProvider interface {
SessionTokenExchangePersister() Persister
}
)

View File

@@ -0,0 +1,207 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package test
import (
"context"
"testing"
"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ory/kratos/persistence"
"github.com/ory/kratos/pkg/testhelpers"
"github.com/ory/kratos/selfservice/sessiontokenexchange"
"github.com/ory/x/randx"
)
type testParams struct {
flowID, sessionID uuid.UUID
initCode, returnToCode string
}
func newParams() testParams {
return testParams{
flowID: uuid.Must(uuid.NewV4()),
sessionID: uuid.Must(uuid.NewV4()),
initCode: randx.MustString(64, randx.AlphaNum),
returnToCode: randx.MustString(64, randx.AlphaNum),
}
}
func (t *testParams) setCodes(e *sessiontokenexchange.Exchanger) {
t.initCode = e.InitCode
t.returnToCode = e.ReturnToCode
}
func TestPersister(ctx context.Context, p interface {
persistence.Persister
}) func(t *testing.T) {
return func(t *testing.T) {
nid, p := testhelpers.NewNetworkUnlessExisting(t, ctx, p)
t.Run("suite=create-update-get", func(t *testing.T) {
t.Parallel()
params := newParams()
t.Run("step=create", func(t *testing.T) {
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
codes, ok, err := p.CodeForFlow(ctx, params.flowID)
assert.True(t, ok)
assert.NoError(t, err)
assert.Equal(t, params.initCode, codes.InitCode)
assert.Equal(t, params.returnToCode, codes.ReturnToCode)
})
t.Run("step=update", func(t *testing.T) {
require.NoError(t, p.UpdateSessionOnExchanger(ctx, params.flowID, params.sessionID))
})
t.Run("step=get", func(t *testing.T) {
e, err := p.GetExchangerFromCode(ctx, params.initCode, params.returnToCode)
require.NoError(t, err)
assert.Equal(t, params.sessionID, e.SessionID.UUID)
assert.Equal(t, nid, e.NID)
})
})
t.Run("suite=CodeForFlow", func(t *testing.T) {
t.Parallel()
t.Run("case=returns false for non-existing flow", func(t *testing.T) {
t.Parallel()
_, ok, err := p.CodeForFlow(ctx, uuid.Must(uuid.NewV4()))
assert.False(t, ok)
assert.NoError(t, err)
})
})
t.Run("suite=MoveToNewFlow", func(t *testing.T) {
t.Parallel()
t.Run("case=move to new flow", func(t *testing.T) {
params := newParams()
other := newParams()
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
require.NoError(t, p.MoveToNewFlow(ctx, params.flowID, other.flowID))
require.NoError(t, p.UpdateSessionOnExchanger(ctx, other.flowID, params.sessionID))
e, err = p.GetExchangerFromCode(ctx, params.initCode, params.returnToCode)
require.NoError(t, err)
assert.Equal(t, params.sessionID, e.SessionID.UUID)
})
})
t.Run("suite=GetExchangerFromCodeAllowPending", func(t *testing.T) {
t.Parallel()
t.Run("case=returns exchanger without session", func(t *testing.T) {
t.Parallel()
params := newParams()
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
e, err = p.GetExchangerFromCodeAllowPending(ctx, params.initCode, params.returnToCode)
require.NoError(t, err)
assert.Equal(t, params.flowID, e.FlowID)
assert.False(t, e.SessionID.Valid)
})
t.Run("case=returns exchanger with session", func(t *testing.T) {
t.Parallel()
params := newParams()
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
require.NoError(t, p.UpdateSessionOnExchanger(ctx, params.flowID, params.sessionID))
e, err = p.GetExchangerFromCodeAllowPending(ctx, params.initCode, params.returnToCode)
require.NoError(t, err)
assert.Equal(t, params.flowID, e.FlowID)
assert.Equal(t, params.sessionID, e.SessionID.UUID)
})
t.Run("case=errors if code is invalid", func(t *testing.T) {
t.Parallel()
other := newParams()
e, err := p.GetExchangerFromCodeAllowPending(ctx, other.initCode, other.returnToCode)
assert.Error(t, err)
assert.Nil(t, e)
})
})
t.Run("suite=GetExchangerFromCode", func(t *testing.T) {
t.Parallel()
t.Run("case=errors if session not found", func(t *testing.T) {
t.Parallel()
params := newParams()
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
e, err = p.GetExchangerFromCode(ctx, params.initCode, params.returnToCode)
assert.Error(t, err)
assert.Nil(t, e)
})
t.Run("case=errors if code is invalid", func(t *testing.T) {
t.Parallel()
params := newParams()
other := newParams()
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
require.NoError(t, p.UpdateSessionOnExchanger(ctx, params.flowID, params.sessionID))
e, err = p.GetExchangerFromCode(ctx, other.initCode, other.returnToCode)
assert.Error(t, err)
assert.Nil(t, e)
})
t.Run("case=errors if code is empty", func(t *testing.T) {
t.Parallel()
params := newParams()
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
require.NoError(t, p.UpdateSessionOnExchanger(ctx, params.flowID, params.sessionID))
e, err = p.GetExchangerFromCode(ctx, "", "")
assert.Error(t, err)
assert.Nil(t, e)
})
t.Run("case=errors if other network ID", func(t *testing.T) {
t.Parallel()
params := newParams()
otherNID := uuid.Must(uuid.NewV4())
e, err := p.CreateSessionTokenExchanger(ctx, params.flowID)
require.NoError(t, err)
params.setCodes(e)
require.NoError(t, p.UpdateSessionOnExchanger(ctx, params.flowID, params.sessionID))
e, err = p.WithNetworkID(otherNID).GetExchangerFromCode(ctx, params.initCode, params.returnToCode)
assert.Error(t, err)
assert.Nil(t, e)
})
})
}
}