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:
131
identity/extension_verification.go
Normal file
131
identity/extension_verification.go
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package identity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ory/jsonschema/v3"
|
||||
"github.com/ory/kratos/schema"
|
||||
"github.com/ory/kratos/x"
|
||||
)
|
||||
|
||||
func init() {
|
||||
jsonschema.Formats["no-validate"] = func(v interface{}) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
type SchemaExtensionVerification struct {
|
||||
lifespan time.Duration
|
||||
l sync.Mutex
|
||||
v []VerifiableAddress
|
||||
i *Identity
|
||||
}
|
||||
|
||||
func NewSchemaExtensionVerification(i *Identity, lifespan time.Duration) *SchemaExtensionVerification {
|
||||
return &SchemaExtensionVerification{i: i, lifespan: lifespan}
|
||||
}
|
||||
|
||||
const (
|
||||
ChannelTypeEmail = "email"
|
||||
ChannelTypeSMS = "sms"
|
||||
)
|
||||
|
||||
func (r *SchemaExtensionVerification) Run(ctx jsonschema.ValidationContext, s schema.ExtensionConfig, value interface{}) error {
|
||||
r.l.Lock()
|
||||
defer r.l.Unlock()
|
||||
|
||||
if s.Verification.Via == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
format, ok := s.RawSchema["format"]
|
||||
if !ok {
|
||||
format = ""
|
||||
}
|
||||
formatString, ok := format.(string)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if formatString == "" {
|
||||
switch s.Verification.Via {
|
||||
case ChannelTypeEmail:
|
||||
formatString = "email"
|
||||
formatter, ok := jsonschema.Formats[formatString]
|
||||
if !ok {
|
||||
supportedKeys := slices.Collect(maps.Keys(jsonschema.Formats))
|
||||
return ctx.Error("format", "format %q is not supported. Supported formats are [%s]", formatString, strings.Join(supportedKeys, ", "))
|
||||
}
|
||||
|
||||
if !formatter(value) {
|
||||
return ctx.Error("format", "%q is not valid %q", value, formatString)
|
||||
}
|
||||
default:
|
||||
return ctx.Error("format", "no format specified. A format is required if verification is enabled. If this was intentional, please set \"format\" to \"no-validate\"")
|
||||
}
|
||||
}
|
||||
|
||||
var normalized string
|
||||
switch formatString {
|
||||
case "email", "tel":
|
||||
var err error
|
||||
normalized, err = x.NormalizeIdentifier(fmt.Sprintf("%s", value), s.Verification.Via)
|
||||
if err != nil {
|
||||
return ctx.Error("format", "%q can not be normalized for format %q", value, formatString)
|
||||
}
|
||||
default:
|
||||
normalized = strings.TrimSpace(fmt.Sprintf("%s", value))
|
||||
}
|
||||
|
||||
address := NewVerifiableAddress(normalized, r.i.ID, s.Verification.Via)
|
||||
r.appendAddress(address)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SchemaExtensionVerification) Finish() error {
|
||||
r.i.VerifiableAddresses = merge(r.v, r.i.VerifiableAddresses)
|
||||
return nil
|
||||
}
|
||||
|
||||
// merge merges the base with the overrides through comparison with `has`. It changes the base slice in place.
|
||||
func merge(base []VerifiableAddress, overrides []VerifiableAddress) []VerifiableAddress {
|
||||
for i := range base {
|
||||
if override := has(overrides, &base[i]); override != nil {
|
||||
base[i] = *override
|
||||
}
|
||||
}
|
||||
|
||||
return base
|
||||
}
|
||||
|
||||
func (r *SchemaExtensionVerification) appendAddress(address *VerifiableAddress) {
|
||||
if h := has(r.i.VerifiableAddresses, address); h != nil {
|
||||
if has(r.v, address) == nil {
|
||||
r.v = append(r.v, *h)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if has(r.v, address) == nil {
|
||||
r.v = append(r.v, *address)
|
||||
}
|
||||
}
|
||||
|
||||
func has(haystack []VerifiableAddress, needle *VerifiableAddress) *VerifiableAddress {
|
||||
// Normalize both sides so pre-normalization persisted values still match.
|
||||
normalizedNeedle := x.GracefulNormalization(needle.Value)
|
||||
for _, has := range haystack {
|
||||
if has.Via == needle.Via && x.GracefulNormalization(has.Value) == normalizedNeedle {
|
||||
return &has
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user