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
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:
237
persistence/sql/persister.go
Normal file
237
persistence/sql/persister.go
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"io/fs"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/identity"
|
||||
"github.com/ory/kratos/persistence"
|
||||
"github.com/ory/kratos/persistence/sql/devices"
|
||||
idpersistence "github.com/ory/kratos/persistence/sql/identity"
|
||||
gomigrations "github.com/ory/kratos/persistence/sql/migrations/go"
|
||||
"github.com/ory/kratos/schema"
|
||||
"github.com/ory/kratos/session"
|
||||
"github.com/ory/pop/v6"
|
||||
"github.com/ory/x/clock"
|
||||
"github.com/ory/x/contextx"
|
||||
"github.com/ory/x/fsx"
|
||||
"github.com/ory/x/logrusx"
|
||||
"github.com/ory/x/networkx"
|
||||
"github.com/ory/x/otelx"
|
||||
"github.com/ory/x/popx"
|
||||
)
|
||||
|
||||
var _ persistence.Persister = new(Persister)
|
||||
|
||||
//go:embed migrations/sql/*.sql
|
||||
var Migrations embed.FS
|
||||
|
||||
type (
|
||||
persisterDependencies interface {
|
||||
logrusx.Provider
|
||||
config.Provider
|
||||
clock.Provider
|
||||
contextx.Provider
|
||||
otelx.Provider
|
||||
schema.IdentitySchemaProvider
|
||||
identity.ValidationProvider
|
||||
}
|
||||
Persister struct {
|
||||
nid uuid.UUID
|
||||
c *pop.Connection
|
||||
mb *popx.MigrationBox
|
||||
mbs popx.MigrationStatuses
|
||||
r persisterDependencies
|
||||
|
||||
identity.PrivilegedPool
|
||||
session.DevicePersister
|
||||
}
|
||||
)
|
||||
|
||||
type options struct {
|
||||
extraMigrations []fs.FS
|
||||
extraGoMigrations popx.Migrations
|
||||
disableLogging bool
|
||||
}
|
||||
|
||||
type Option = func(o *options)
|
||||
|
||||
func WithExtraMigrations(fss ...fs.FS) Option {
|
||||
return func(o *options) {
|
||||
o.extraMigrations = fss
|
||||
}
|
||||
}
|
||||
|
||||
func WithExtraGoMigrations(ms ...popx.Migration) Option {
|
||||
return func(o *options) {
|
||||
o.extraGoMigrations = ms
|
||||
}
|
||||
}
|
||||
|
||||
func WithDisabledLogging(v bool) Option {
|
||||
return func(o *options) {
|
||||
o.disableLogging = v
|
||||
}
|
||||
}
|
||||
|
||||
func NewPersister(r persisterDependencies, c *pop.Connection, opts ...Option) (*Persister, error) {
|
||||
o := &options{}
|
||||
for _, f := range opts {
|
||||
f(o)
|
||||
}
|
||||
logger := r.Logger()
|
||||
if o.disableLogging {
|
||||
logger.Logrus().SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
m, err := popx.NewMigrationBox(
|
||||
fsx.Merge(append([]fs.FS{Migrations, networkx.Migrations}, o.extraMigrations...)...),
|
||||
c, logger,
|
||||
popx.WithGoMigrations(slices.Concat(gomigrations.All, o.extraGoMigrations)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Persister{
|
||||
c: c,
|
||||
mb: m,
|
||||
r: r,
|
||||
PrivilegedPool: idpersistence.NewPersister(r, c),
|
||||
DevicePersister: devices.NewPersister(r, c),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Persister) NetworkID(ctx context.Context) uuid.UUID {
|
||||
return p.r.Contextualizer().Network(ctx, p.nid)
|
||||
}
|
||||
|
||||
func (p Persister) WithNetworkID(nid uuid.UUID) persistence.Persister {
|
||||
p.nid = nid
|
||||
if pp, ok := p.PrivilegedPool.(interface {
|
||||
WithNetworkID(uuid.UUID) identity.PrivilegedPool
|
||||
}); ok {
|
||||
p.PrivilegedPool = pp.WithNetworkID(nid)
|
||||
}
|
||||
if dp, ok := p.DevicePersister.(interface {
|
||||
WithNetworkID(uuid.UUID) session.DevicePersister
|
||||
}); ok {
|
||||
p.DevicePersister = dp.WithNetworkID(nid)
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p *Persister) DetermineNetwork(ctx context.Context) (*networkx.Network, error) {
|
||||
return networkx.Determine(p.Connection(ctx))
|
||||
}
|
||||
|
||||
func (p *Persister) Connection(ctx context.Context) *pop.Connection {
|
||||
return p.c.WithContext(ctx)
|
||||
}
|
||||
|
||||
func (p *Persister) MigrationStatus(ctx context.Context) (_ popx.MigrationStatuses, err error) {
|
||||
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.MigrationStatus")
|
||||
defer otelx.End(span, &err)
|
||||
|
||||
if p.mbs != nil {
|
||||
return p.mbs, nil
|
||||
}
|
||||
|
||||
status, err := p.mb.Status(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if !status.HasPending() {
|
||||
p.mbs = status
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func (p *Persister) MigrateDown(ctx context.Context, steps int) error {
|
||||
return p.mb.Down(ctx, steps)
|
||||
}
|
||||
|
||||
func (p *Persister) MigrateUp(ctx context.Context) error {
|
||||
return p.mb.Up(ctx)
|
||||
}
|
||||
|
||||
func (p *Persister) MigrationBox() *popx.MigrationBox {
|
||||
return p.mb
|
||||
}
|
||||
|
||||
func (p *Persister) Close(ctx context.Context) error {
|
||||
return errors.WithStack(p.GetConnection(ctx).Close())
|
||||
}
|
||||
|
||||
func (p *Persister) Ping(ctx context.Context) error {
|
||||
return errors.WithStack(p.c.Store.SQLDB().PingContext(ctx))
|
||||
}
|
||||
|
||||
func (p *Persister) CleanupDatabase(ctx context.Context, wait time.Duration, older time.Duration, batchSize int) error {
|
||||
currentTime := time.Now().Add(-older)
|
||||
p.r.Logger().Printf("Cleaning up records older than %s\n", currentTime)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired sessions")
|
||||
if err := p.DeleteExpiredSessions(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired continuity containers")
|
||||
if err := p.DeleteExpiredContinuitySessions(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired login flows")
|
||||
if err := p.DeleteExpiredLoginFlows(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired recovery flows")
|
||||
if err := p.DeleteExpiredRecoveryFlows(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired registration flows")
|
||||
if err := p.DeleteExpiredRegistrationFlows(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired settings flows")
|
||||
if err := p.DeleteExpiredSettingsFlows(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired verification flows")
|
||||
if err := p.DeleteExpiredVerificationFlows(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Cleaning up expired session token exchangers")
|
||||
if err := p.DeleteExpiredExchangers(ctx, currentTime, batchSize); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(wait)
|
||||
|
||||
p.r.Logger().Println("Successfully cleaned up the latest batch of the SQL database! " +
|
||||
"This should be re-run periodically, to be sure that all expired data is purged.")
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user