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
314 lines
8.2 KiB
Go
314 lines
8.2 KiB
Go
// Copyright © 2023 Ory Corp
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package driver
|
|
|
|
import (
|
|
"context"
|
|
"io/fs"
|
|
|
|
"github.com/gorilla/sessions"
|
|
|
|
"github.com/ory/x/httpx"
|
|
|
|
"github.com/ory/kratos/cipher"
|
|
"github.com/ory/kratos/continuity"
|
|
"github.com/ory/kratos/courier"
|
|
"github.com/ory/kratos/driver/config"
|
|
"github.com/ory/kratos/hash"
|
|
"github.com/ory/kratos/identity"
|
|
"github.com/ory/kratos/persistence"
|
|
"github.com/ory/kratos/schema"
|
|
"github.com/ory/kratos/selfservice/errorx"
|
|
"github.com/ory/kratos/selfservice/flow/login"
|
|
"github.com/ory/kratos/selfservice/flow/logout"
|
|
"github.com/ory/kratos/selfservice/flow/recovery"
|
|
"github.com/ory/kratos/selfservice/flow/registration"
|
|
"github.com/ory/kratos/selfservice/flow/settings"
|
|
"github.com/ory/kratos/selfservice/flow/verification"
|
|
"github.com/ory/kratos/selfservice/sessiontokenexchange"
|
|
"github.com/ory/kratos/selfservice/strategy/code"
|
|
"github.com/ory/kratos/selfservice/strategy/link"
|
|
password2 "github.com/ory/kratos/selfservice/strategy/password"
|
|
"github.com/ory/kratos/session"
|
|
"github.com/ory/kratos/x"
|
|
"github.com/ory/kratos/x/nosurfx"
|
|
"github.com/ory/nosurf"
|
|
"github.com/ory/pop/v6"
|
|
"github.com/ory/x/clock"
|
|
"github.com/ory/x/configx"
|
|
"github.com/ory/x/contextx"
|
|
"github.com/ory/x/healthx"
|
|
"github.com/ory/x/httprouterx"
|
|
"github.com/ory/x/jsonnetsecure"
|
|
"github.com/ory/x/logrusx"
|
|
"github.com/ory/x/otelx"
|
|
"github.com/ory/x/popx"
|
|
"github.com/ory/x/servicelocatorx"
|
|
)
|
|
|
|
type Registry interface {
|
|
Init(ctx context.Context, ctxer contextx.Contextualizer, opts ...RegistryOption) error
|
|
|
|
SetLogger(l *logrusx.Logger)
|
|
SetJSONNetVMProvider(jsonnetsecure.VMProvider)
|
|
|
|
// Clock returns the time source used for time-dependent behavior such as
|
|
// flow expiry. Tests can override it via RegistryDefault.SetClock.
|
|
Clock() clock.Clock
|
|
|
|
WithCSRFHandler(c nosurf.Handler)
|
|
WithCSRFTokenGenerator(cg nosurfx.CSRFToken)
|
|
|
|
HealthHandler(ctx context.Context) *healthx.Handler
|
|
CookieManager(ctx context.Context) sessions.StoreExact
|
|
ContinuityCookieManager(ctx context.Context) sessions.StoreExact
|
|
|
|
RegisterPublicRoutes(ctx context.Context, public *httprouterx.RouterPublic)
|
|
RegisterAdminRoutes(ctx context.Context, admin *httprouterx.RouterAdmin)
|
|
Tracer(context.Context) *otelx.Tracer
|
|
SetTracer(*otelx.Tracer)
|
|
|
|
config.Provider
|
|
CourierConfig() config.CourierConfigs
|
|
SetConfig(c *config.Config)
|
|
SetContextualizer(ctxer contextx.Contextualizer)
|
|
|
|
nosurfx.CSRFProvider
|
|
httpx.WriterProvider
|
|
logrusx.Provider
|
|
httpx.ClientProvider
|
|
jsonnetsecure.VMProvider
|
|
|
|
continuity.ManagementProvider
|
|
continuity.PersistenceProvider
|
|
|
|
cipher.Provider
|
|
|
|
courier.Provider
|
|
|
|
persistence.Provider
|
|
|
|
errorx.ManagementProvider
|
|
errorx.HandlerProvider
|
|
errorx.PersistenceProvider
|
|
|
|
hash.HashProvider
|
|
|
|
identity.HandlerProvider
|
|
identity.ValidationProvider
|
|
identity.PoolProvider
|
|
identity.PrivilegedPoolProvider
|
|
identity.ManagementProvider
|
|
identity.ActiveCredentialsCounterStrategyProvider
|
|
|
|
courier.HandlerProvider
|
|
courier.PersistenceProvider
|
|
|
|
schema.HandlerProvider
|
|
schema.IdentitySchemaProvider
|
|
|
|
password2.ValidationProvider
|
|
|
|
session.HandlerProvider
|
|
session.ManagementProvider
|
|
session.PersistenceProvider
|
|
session.TokenizerProvider
|
|
|
|
settings.HandlerProvider
|
|
settings.ErrorHandlerProvider
|
|
settings.FlowPersistenceProvider
|
|
settings.StrategyProvider
|
|
|
|
login.FlowPersistenceProvider
|
|
login.ErrorHandlerProvider
|
|
login.HooksProvider
|
|
login.HookExecutorProvider
|
|
login.HandlerProvider
|
|
login.StrategyProvider
|
|
|
|
logout.HandlerProvider
|
|
|
|
registration.FlowPersistenceProvider
|
|
registration.ErrorHandlerProvider
|
|
registration.HooksProvider
|
|
registration.HookExecutorProvider
|
|
registration.HandlerProvider
|
|
registration.StrategyProvider
|
|
|
|
verification.FlowPersistenceProvider
|
|
verification.ErrorHandlerProvider
|
|
verification.HandlerProvider
|
|
verification.StrategyProvider
|
|
|
|
sessiontokenexchange.PersistenceProvider
|
|
|
|
link.SenderProvider
|
|
link.VerificationTokenPersistenceProvider
|
|
link.RecoveryTokenPersistenceProvider
|
|
|
|
code.SenderProvider
|
|
code.RecoveryCodePersistenceProvider
|
|
|
|
recovery.FlowPersistenceProvider
|
|
recovery.ErrorHandlerProvider
|
|
recovery.HandlerProvider
|
|
recovery.StrategyProvider
|
|
|
|
nosurfx.CSRFTokenGeneratorProvider
|
|
}
|
|
|
|
func NewRegistryFromDSN(ctx context.Context, c *config.Config, l *logrusx.Logger) (*RegistryDefault, error) {
|
|
reg := NewRegistryDefault()
|
|
|
|
tracer, err := otelx.New("Ory Kratos", l, c.Tracing(ctx))
|
|
if err != nil {
|
|
l.WithError(err).Fatalf("failed to initialize tracer")
|
|
tracer = otelx.NewNoop()
|
|
}
|
|
reg.SetTracer(tracer)
|
|
reg.SetLogger(l)
|
|
reg.SetConfig(c)
|
|
|
|
return reg, nil
|
|
}
|
|
|
|
type options struct {
|
|
skipNetworkInit bool
|
|
config *config.Config
|
|
configOptions []configx.OptionModifier
|
|
replaceTracer func(*otelx.Tracer) *otelx.Tracer
|
|
replaceIdentitySchemaProvider func(Registry) schema.IdentitySchemaProvider
|
|
inspect func(Registry) error
|
|
extraMigrations []fs.FS
|
|
extraGoMigrations popx.Migrations
|
|
replacementStrategies []NewStrategy
|
|
extraHooks map[string]NewHookFn
|
|
extraHashers map[string]NewHasherFn
|
|
extraHandlers []NewHandler
|
|
disableMigrationLogging bool
|
|
jsonnetPool jsonnetsecure.Pool
|
|
serviceLocatorOptions []servicelocatorx.Option
|
|
dbOpts []func(details *pop.ConnectionDetails)
|
|
}
|
|
|
|
type RegistryOption func(*options)
|
|
|
|
// WithDBOptions adds database connection options that will be applied to the
|
|
// underlying connection.
|
|
func WithDBOptions(opts ...func(details *pop.ConnectionDetails)) RegistryOption {
|
|
return func(o *options) {
|
|
o.dbOpts = append(o.dbOpts, opts...)
|
|
}
|
|
}
|
|
|
|
func SkipNetworkInit(o *options) {
|
|
o.skipNetworkInit = true
|
|
}
|
|
|
|
func WithJsonnetPool(pool jsonnetsecure.Pool) RegistryOption {
|
|
return func(o *options) {
|
|
o.jsonnetPool = pool
|
|
}
|
|
}
|
|
|
|
func WithConfig(config *config.Config) RegistryOption {
|
|
return func(o *options) {
|
|
o.config = config
|
|
}
|
|
}
|
|
|
|
func WithConfigOptions(opts ...configx.OptionModifier) RegistryOption {
|
|
return func(o *options) {
|
|
o.configOptions = append(o.configOptions, opts...)
|
|
}
|
|
}
|
|
|
|
func WithIdentitySchemaProvider(f func(r Registry) schema.IdentitySchemaProvider) RegistryOption {
|
|
return func(o *options) {
|
|
o.replaceIdentitySchemaProvider = f
|
|
}
|
|
}
|
|
|
|
func ReplaceTracer(f func(*otelx.Tracer) *otelx.Tracer) RegistryOption {
|
|
return func(o *options) {
|
|
o.replaceTracer = f
|
|
}
|
|
}
|
|
|
|
type NewStrategy func(deps any) any
|
|
|
|
// WithReplaceStrategies adds a strategy to the registry. This is useful if you want to
|
|
// add a custom strategy to the registry. Default strategies with the same
|
|
// name/ID will be overwritten.
|
|
func WithReplaceStrategies(s ...NewStrategy) RegistryOption {
|
|
return func(o *options) {
|
|
o.replacementStrategies = append(o.replacementStrategies, s...)
|
|
}
|
|
}
|
|
|
|
type NewHookFn func(config.SelfServiceHook, Registry) any
|
|
|
|
func WithExtraHooks(hooks map[string]NewHookFn) RegistryOption {
|
|
return func(o *options) {
|
|
o.extraHooks = hooks
|
|
}
|
|
}
|
|
|
|
type NewHasherFn func(reg Registry) hash.Hasher
|
|
|
|
// WithExtraHashers registers additional password hashers, keyed by the
|
|
// hashers.algorithm value that selects them. An extra hasher takes precedence
|
|
// over a built-in hasher with the same name.
|
|
func WithExtraHashers(hashers map[string]NewHasherFn) RegistryOption {
|
|
return func(o *options) {
|
|
o.extraHashers = hashers
|
|
}
|
|
}
|
|
|
|
type NewHandler func(deps any) x.Handler
|
|
|
|
func WithExtraHandlers(handlers ...NewHandler) RegistryOption {
|
|
return func(o *options) {
|
|
o.extraHandlers = handlers
|
|
}
|
|
}
|
|
|
|
func Inspect(f func(reg Registry) error) RegistryOption {
|
|
return func(o *options) {
|
|
o.inspect = f
|
|
}
|
|
}
|
|
|
|
func WithExtraMigrations(m ...fs.FS) RegistryOption {
|
|
return func(o *options) {
|
|
o.extraMigrations = append(o.extraMigrations, m...)
|
|
}
|
|
}
|
|
|
|
func WithExtraGoMigrations(m ...popx.Migration) RegistryOption {
|
|
return func(o *options) {
|
|
o.extraGoMigrations = append(o.extraGoMigrations, m...)
|
|
}
|
|
}
|
|
|
|
func WithDisabledMigrationLogging() RegistryOption {
|
|
return func(o *options) {
|
|
o.disableMigrationLogging = true
|
|
}
|
|
}
|
|
|
|
func WithServiceLocatorOptions(opts ...servicelocatorx.Option) RegistryOption {
|
|
return func(o *options) {
|
|
o.serviceLocatorOptions = append(o.serviceLocatorOptions, opts...)
|
|
}
|
|
}
|
|
|
|
func newOptions(os []RegistryOption) *options {
|
|
o := new(options)
|
|
for _, f := range os {
|
|
f(o)
|
|
}
|
|
return o
|
|
}
|