Files
upstream-ory-kratos/persistence/sql/persister_sessiontokenexchanger.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

145 lines
4.6 KiB
Go

// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package sql
import (
"context"
"fmt"
"time"
"github.com/gofrs/uuid"
"github.com/pkg/errors"
"github.com/ory/kratos/selfservice/sessiontokenexchange"
"github.com/ory/pop/v6"
"github.com/ory/x/dbal"
"github.com/ory/x/otelx"
"github.com/ory/x/randx"
"github.com/ory/x/sqlcon"
)
var _ sessiontokenexchange.Persister = new(Persister)
func updateLimitClause(conn *pop.Connection) string {
// Not all databases support limiting in update clauses.
switch conn.Dialect.Name() {
case "sqlite3", dbal.DriverPostgreSQL, dbal.DriverYugabyteDB:
return ""
default:
return "LIMIT 1"
}
}
func (p *Persister) CreateSessionTokenExchanger(ctx context.Context, flowID uuid.UUID) (e *sessiontokenexchange.Exchanger, err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.CreateSessionTokenExchanger")
defer otelx.End(span, &err)
e = &sessiontokenexchange.Exchanger{
NID: p.NetworkID(ctx),
FlowID: flowID,
InitCode: randx.MustString(64, randx.AlphaNum),
ReturnToCode: randx.MustString(64, randx.AlphaNum),
}
return e, p.GetConnection(ctx).Create(e)
}
func (p *Persister) GetExchangerFromCode(ctx context.Context, initCode string, returnToCode string) (e *sessiontokenexchange.Exchanger, err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetExchangerFromCode")
defer otelx.End(span, &err)
e = new(sessiontokenexchange.Exchanger)
conn := p.GetConnection(ctx)
if err = conn.Where(`
nid = ? AND
init_code = ? AND init_code <> '' AND
return_to_code = ? AND return_to_code <> '' AND
session_id IS NOT NULL`,
p.NetworkID(ctx), initCode, returnToCode).First(e); err != nil {
return nil, sqlcon.HandleError(err)
}
return e, nil
}
func (p *Persister) GetExchangerFromCodeAllowPending(ctx context.Context, initCode string, returnToCode string) (e *sessiontokenexchange.Exchanger, err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetExchangerFromCodeAllowPending")
defer otelx.End(span, &err)
e = new(sessiontokenexchange.Exchanger)
conn := p.GetConnection(ctx)
if err = conn.Where(`
nid = ? AND
init_code = ? AND init_code <> '' AND
return_to_code = ? AND return_to_code <> ''`,
p.NetworkID(ctx), initCode, returnToCode).First(e); err != nil {
return nil, sqlcon.HandleError(err)
}
return e, nil
}
func (p *Persister) UpdateSessionOnExchanger(ctx context.Context, flowID uuid.UUID, sessionID uuid.UUID) (err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.UpdateSessionOnExchanger")
defer otelx.End(span, &err)
conn := p.GetConnection(ctx)
query := fmt.Sprintf("UPDATE %s SET session_id = ? WHERE flow_id = ? AND nid = ? %s",
conn.Dialect.Quote(new(sessiontokenexchange.Exchanger).TableName()),
updateLimitClause(conn),
)
return sqlcon.HandleError(conn.RawQuery(query, sessionID, flowID, p.NetworkID(ctx)).Exec())
}
func (p *Persister) CodeForFlow(ctx context.Context, flowID uuid.UUID) (codes *sessiontokenexchange.Codes, found bool, err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.CodeForFlow")
defer otelx.End(span, &err)
var e sessiontokenexchange.Exchanger
switch err = sqlcon.HandleError(p.GetConnection(ctx).
Where("flow_id = ? AND nid = ? AND init_code <> '' and return_to_code <> ''", flowID, p.NetworkID(ctx)).
First(&e)); {
case err == nil:
return &sessiontokenexchange.Codes{
InitCode: e.InitCode,
ReturnToCode: e.ReturnToCode,
}, true, nil
case errors.Is(err, sqlcon.ErrNoRows()):
return nil, false, nil
default:
return nil, false, err
}
}
func (p *Persister) MoveToNewFlow(ctx context.Context, oldFlow, newFlow uuid.UUID) (err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.MoveToNewFlow")
defer otelx.End(span, &err)
conn := p.GetConnection(ctx)
query := fmt.Sprintf("UPDATE %s SET flow_id = ? WHERE flow_id = ? AND nid = ? %s",
conn.Dialect.Quote(new(sessiontokenexchange.Exchanger).TableName()),
updateLimitClause(conn),
)
return sqlcon.HandleError(conn.RawQuery(query, newFlow, oldFlow, p.NetworkID(ctx)).Exec())
}
func (p *Persister) DeleteExpiredExchangers(ctx context.Context, at time.Time, limit int) error {
expiredAfter := at.Add(1 * time.Hour)
conn := p.GetConnection(ctx)
//#nosec G201 -- TableName is static
err := conn.RawQuery(fmt.Sprintf(
"DELETE FROM %[1]s WHERE id in (SELECT id FROM (SELECT id FROM %[1]s c WHERE created_at <= ? and nid = ? ORDER BY created_at ASC LIMIT ?) AS s)",
sessiontokenexchange.Exchanger{}.TableName(),
),
expiredAfter,
p.NetworkID(ctx),
limit,
).Exec()
return sqlcon.HandleError(err)
}