Files
zitadel/backend/v3/domain/session_check_util.go
T
c6386cb807 feat: rt recovery code check (#11848)
# Which Problems Are Solved

Adding recovery code check step required for the CreateSession RT
implementation.

# How the Problems Are Solved

- Introduce `RecoveryCodeCheckCommand` (validate/execute/events) for
session creation checks
- Add unit tests

# Additional Changes
- refactor password-check code to reuse a shared lockout-policy helper
- add some missing error translations in `internal/static/i18n/en.yaml`

# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11035

---------

Co-authored-by: Silvan <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-03-23 10:56:40 +01:00

46 lines
2.0 KiB
Go

package domain
import (
"context"
"github.com/muhlemmer/gu"
"github.com/zitadel/zitadel/backend/v3/storage/database"
"github.com/zitadel/zitadel/internal/zerrors"
)
type verifierFn func(encoded, password string) (updated string, err error)
func GetLockoutPolicy(ctx context.Context, opts *InvokeOpts, instanceID, orgID string) (*LockoutSettings, error) {
lockoutSettingRepo := opts.lockoutSettingRepo
// We need the organization lockout policy first, and if not available, the instance (default) policy.
// So we retrieve all records with a matching instance ID and organization ID OR
// all records with a matching instance ID and NULL (or empty) organization ID.
// Then we assume NULLs are sorted as largest numbers (that's the case in Postgres),
// so we sort ascending by organization ID.
// We limit the result to 1 so that we get either the org policy or the instance one.
settings, err := lockoutSettingRepo.List(ctx, opts.DB(),
listLockoutSettingCondition(lockoutSettingRepo, instanceID, orgID),
database.WithOrderByAscending(lockoutSettingRepo.OrganizationIDColumn(), lockoutSettingRepo.InstanceIDColumn()),
database.WithLimit(1),
)
if err != nil {
return nil, zerrors.ThrowInternal(err, "DOM-3B8Z6s", "failed fetching lockout settings")
}
if rowsReturned := len(settings); rowsReturned != 1 {
return nil, zerrors.ThrowInternal(NewRowsReturnedMismatchError(1, int64(rowsReturned)), "DOM-mmsrCt", "unexpected number of rows returned")
}
return settings[0], nil
}
func listLockoutSettingCondition(repo LockoutSettingsRepository, instanceID, orgID string) database.QueryOption {
instanceAndOrg := database.And(repo.InstanceIDCondition(instanceID), repo.OrganizationIDCondition(&orgID))
orgNullOrEmpty := database.Or(repo.OrganizationIDCondition(nil), repo.OrganizationIDCondition(gu.Ptr("")))
onlyInstance := database.And(repo.InstanceIDCondition(instanceID), orgNullOrEmpty)
return database.WithCondition(database.Or(instanceAndOrg, onlyInstance))
}