Files
zitadel/internal/query/projection/user_relational.go
T
Gayathri VijayanandGitHub fb35fdd3c7 feat: add recovery codes to user repository (#11702)
# Which Problems Are Solved

Adds a repository implementation to add/remove recovery codes to the
users relational table.

# How the Problems Are Solved

This is achieved by:
* adding the following columns to the users table: `recovery_codes`,
`recovery_code_last_successful_check`, `recovery_code_failed_attempts`
* adding the `RecoveryCodes` field to the `HumanUser` domain with fields
to set recovery `codes`, `lastSuccessfullyCheckedAt` timestamp, and
`failedAttempts`
* setting `recoveryCodes` in the `Get` user query statement to return a
json object with details related to the recovery codes
* adding the repository-layer implementation to add/remove recovery
codes and set fields related to recovery code checks.
* adding projection reducers to handle the following events:
`HumanRecoveryCodesAddedEvent`, `HumanRecoveryCodesRemovedEvent`,
`HumanRecoveryCodeCheckSucceededEvent`, and
`HumanRecoveryCodeCheckFailedEvent`
* adding unit tests

# Additional Changes
* fix the error message when the recovery is empty in
`internal/command/user_human_recovery_codes.go`
* add a new error message for empty recovery code during checks in
`en.yaml`

# Additional Context
- Closes https://github.com/zitadel/zitadel/issues/11212
- Follow-up: integration tests for the reducers will be added in a
different PR after this
[PR](https://github.com/zitadel/zitadel/pull/11478) is merged
2026-02-26 19:22:37 +01:00

2252 lines
71 KiB
Go

package projection
import (
"context"
"database/sql"
"time"
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
v3_sql "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/sql"
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
"github.com/zitadel/zitadel/internal/crypto"
old_domain "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/zerrors"
)
const (
UserRelationProjectionTable = "zitadel.users"
)
type userRelationalProjection struct{}
func (*userRelationalProjection) Name() string {
return UserRelationProjectionTable
}
func newUserRelationalProjection(ctx context.Context, config handler.Config) *handler.Handler {
return handler.NewHandler(ctx, &config, new(userRelationalProjection))
}
func (p *userRelationalProjection) Reducers() []handler.AggregateReducer {
return []handler.AggregateReducer{
{
Aggregate: user.AggregateType,
EventReducers: []handler.EventReducer{
{
Event: user.UserV1AddedType,
Reduce: p.reduceHumanAdded,
},
{
Event: user.HumanAddedType,
Reduce: p.reduceHumanAdded,
},
{
Event: user.UserV1RegisteredType,
Reduce: p.reduceHumanRegistered,
},
{
Event: user.HumanRegisteredType,
Reduce: p.reduceHumanRegistered,
},
{
Event: user.UserLockedType,
Reduce: p.reduceUserLocked,
},
{
Event: user.UserUnlockedType,
Reduce: p.reduceUserUnlocked,
},
{
Event: user.UserDeactivatedType,
Reduce: p.reduceUserDeactivated,
},
{
Event: user.UserReactivatedType,
Reduce: p.reduceUserReactivated,
},
{
Event: user.UserRemovedType,
Reduce: p.reduceUserRemoved,
},
{
Event: user.UserUserNameChangedType,
Reduce: p.reduceUsernameChanged,
},
{
Event: user.UserDomainClaimedType,
Reduce: p.reduceDomainClaimed,
},
{
Event: user.HumanProfileChangedType,
Reduce: p.reduceHumanProfileChanged,
},
{
Event: user.UserV1ProfileChangedType,
Reduce: p.reduceHumanProfileChanged,
},
{
Event: user.HumanEmailChangedType,
Reduce: p.reduceHumanEmailChanged,
},
{
Event: user.UserV1EmailChangedType,
Reduce: p.reduceHumanEmailChanged,
},
{
Event: user.HumanEmailVerifiedType,
Reduce: p.reduceHumanEmailVerified,
},
{
Event: user.UserV1EmailVerifiedType,
Reduce: p.reduceHumanEmailVerified,
},
{
Event: user.HumanEmailCodeAddedType,
Reduce: p.reduceHumanEmailCodeAdded,
},
{
Event: user.UserV1EmailCodeAddedType,
Reduce: p.reduceHumanEmailCodeAdded,
},
{
Event: user.HumanEmailVerificationFailedType,
Reduce: p.reduceHumanEmailVerificationFailed,
},
{
Event: user.UserV1EmailVerificationFailedType,
Reduce: p.reduceHumanEmailVerificationFailed,
},
{
Event: user.HumanPhoneChangedType,
Reduce: p.reduceHumanPhoneChanged,
},
{
Event: user.UserV1PhoneChangedType,
Reduce: p.reduceHumanPhoneChanged,
},
{
Event: user.HumanPhoneRemovedType,
Reduce: p.reduceHumanPhoneRemoved,
},
{
Event: user.UserV1PhoneRemovedType,
Reduce: p.reduceHumanPhoneRemoved,
},
{
Event: user.HumanPhoneVerifiedType,
Reduce: p.reduceHumanPhoneVerified,
},
{
Event: user.UserV1PhoneVerifiedType,
Reduce: p.reduceHumanPhoneVerified,
},
{
Event: user.HumanPhoneCodeAddedType,
Reduce: p.reduceHumanPhoneCodeAdded,
},
{
Event: user.UserV1PhoneCodeAddedType,
Reduce: p.reduceHumanPhoneCodeAdded,
},
{
Event: user.HumanPhoneVerificationFailedType,
Reduce: p.reduceHumanPhoneVerificationFailed,
},
{
Event: user.UserV1PhoneVerificationFailedType,
Reduce: p.reduceHumanPhoneVerificationFailed,
},
{
Event: user.HumanAvatarAddedType,
Reduce: p.reduceHumanAvatarAdded,
},
{
Event: user.HumanAvatarRemovedType,
Reduce: p.reduceHumanAvatarRemoved,
},
{
Event: user.HumanPasswordChangedType,
Reduce: p.reduceHumanPasswordChanged,
},
{
Event: user.UserV1PasswordChangedType,
Reduce: p.reduceHumanPasswordChanged,
},
{
Event: user.HumanPasswordCodeAddedType,
Reduce: p.reduceHumanPasswordCodeAdded,
},
{
Event: user.UserV1PasswordCodeAddedType,
Reduce: p.reduceHumanPasswordCodeAdded,
},
{
Event: user.HumanPasswordCheckSucceededType,
Reduce: p.reduceHumanPasswordCheckSucceeded,
},
{
Event: user.UserV1PasswordCheckSucceededType,
Reduce: p.reduceHumanPasswordCheckSucceeded,
},
{
Event: user.HumanPasswordCheckFailedType,
Reduce: p.reduceHumanPasswordCheckFailed,
},
{
Event: user.UserV1PasswordCheckFailedType,
Reduce: p.reduceHumanPasswordCheckFailed,
},
{
Event: user.HumanPasswordHashUpdatedType,
Reduce: p.reduceHumanPasswordHashUpdated,
},
{
Event: user.MachineAddedEventType,
Reduce: p.reduceMachineAdded,
},
{
Event: user.MachineChangedEventType,
Reduce: p.reduceMachineChanged,
},
{
Event: user.MachineSecretSetType,
Reduce: p.reduceMachineSecretSet,
},
{
Event: user.MachineSecretHashUpdatedType,
Reduce: p.reduceMachineSecretHashUpdated,
},
{
Event: user.MachineSecretRemovedType,
Reduce: p.reduceMachineSecretRemoved,
},
{
Event: user.MachineKeyAddedEventType,
Reduce: p.reduceMachineKeyAdded,
},
{
Event: user.MachineKeyRemovedEventType,
Reduce: p.reduceMachineKeyRemoved,
},
{
Event: user.UserV1MFAInitSkippedType,
Reduce: p.reduceMFAInitSkipped,
},
{
Event: user.HumanMFAInitSkippedType,
Reduce: p.reduceMFAInitSkipped,
},
{
Event: user.PersonalAccessTokenAddedType,
Reduce: p.reducePersonalAccessTokenAdded,
},
{
Event: user.PersonalAccessTokenRemovedType,
Reduce: p.reducePersonalAccessTokenRemoved,
},
{
Event: user.MetadataSetType,
Reduce: p.reduceMetadataSet,
},
{
Event: user.MetadataRemovedType,
Reduce: p.reduceMetadataRemoved,
},
{
Event: user.MetadataRemovedAllType,
Reduce: p.reduceMetadataRemovedAll,
},
{
Event: user.HumanPasswordlessTokenAddedType,
Reduce: p.reducePasskeyAdded,
},
{
Event: user.HumanPasswordlessTokenVerifiedType,
Reduce: p.reducePasskeyVerified,
},
{
Event: user.HumanPasswordlessTokenSignCountChangedType,
Reduce: p.reducePasskeySignCountSet,
},
{
Event: user.HumanPasswordlessTokenRemovedType,
Reduce: p.reducePasskeyRemoved,
},
{
Event: user.HumanU2FTokenAddedType,
Reduce: p.reducePasskeyAdded,
},
{
Event: user.HumanU2FTokenVerifiedType,
Reduce: p.reducePasskeyVerified,
},
{
Event: user.HumanU2FTokenSignCountChangedType,
Reduce: p.reducePasskeySignCountSet,
},
{
Event: user.HumanU2FTokenRemovedType,
Reduce: p.reducePasskeyRemoved,
},
{
Event: user.HumanPasswordlessInitCodeAddedType,
Reduce: p.reducePasskeyInitCodeAdded,
},
{
Event: user.HumanPasswordlessInitCodeCheckFailedType,
Reduce: p.reducePasskeyInitCodeCheckFailed,
},
{
Event: user.HumanPasswordlessInitCodeCheckSucceededType,
Reduce: p.reducePasskeyInitCodeCheckSucceeded,
},
{
Event: user.HumanPasswordlessInitCodeRequestedType,
Reduce: p.reducePasskeyInitCodeRequested,
},
{
Event: user.UserIDPLinkAddedType,
Reduce: p.reduceIDPLinkAdded,
},
{
Event: user.UserIDPLinkCascadeRemovedType,
Reduce: p.reduceIDPLinkCascadeRemoved,
},
{
Event: user.UserIDPLinkRemovedType,
Reduce: p.reduceIDPLinkRemoved,
},
{
Event: user.UserIDPExternalIDMigratedType,
Reduce: p.reduceIDPLinkUserIDMigrated,
},
{
Event: user.UserIDPExternalUsernameChangedType,
Reduce: p.reduceIDPLinkUsernameChanged,
},
{
Event: user.HumanMFAOTPAddedType,
Reduce: p.reduceTOTPAdded,
},
{
Event: user.UserV1MFAOTPAddedType,
Reduce: p.reduceTOTPAdded,
},
{
Event: user.HumanMFAOTPVerifiedType,
Reduce: p.reduceTOTPVerified,
},
{
Event: user.UserV1MFAOTPVerifiedType,
Reduce: p.reduceTOTPVerified,
},
{
Event: user.HumanMFAOTPRemovedType,
Reduce: p.reduceTOTPRemoved,
},
{
Event: user.UserV1MFAOTPRemovedType,
Reduce: p.reduceTOTPRemoved,
},
{
Event: user.HumanMFAOTPCheckSucceededType,
Reduce: p.reduceTOTPCheckSucceeded,
},
{
Event: user.UserV1MFAOTPCheckSucceededType,
Reduce: p.reduceTOTPCheckSucceeded,
},
{
Event: user.HumanMFAOTPCheckFailedType,
Reduce: p.reduceTOTPCheckFailed,
},
{
Event: user.UserV1MFAOTPCheckFailedType,
Reduce: p.reduceTOTPCheckFailed,
},
{
Event: user.HumanOTPSMSAddedType,
Reduce: p.reduceOTPSMSEnabled,
},
{
Event: user.HumanOTPSMSRemovedType,
Reduce: p.reduceOTPSMSDisabled,
},
{
Event: user.HumanOTPSMSCheckSucceededType,
Reduce: p.reduceOTPSMSCheckSucceeded,
},
{
Event: user.HumanOTPSMSCheckFailedType,
Reduce: p.reduceOTPSMSCheckFailed,
},
{
Event: user.HumanOTPEmailAddedType,
Reduce: p.reduceOTPEmailEnabled,
},
{
Event: user.HumanOTPEmailRemovedType,
Reduce: p.reduceOTPEmailDisabled,
},
{
Event: user.HumanOTPEmailCheckSucceededType,
Reduce: p.reduceOTPEmailCheckSucceeded,
},
{
Event: user.HumanOTPEmailCheckFailedType,
Reduce: p.reduceOTPEmailCheckFailed,
},
{
Event: user.HumanInviteCodeAddedType,
Reduce: p.reduceInviteCodeAdded,
},
{
Event: user.HumanInviteCheckSucceededType,
Reduce: p.reduceInviteCheckSucceeded,
},
{
Event: user.HumanInviteCheckFailedType,
Reduce: p.reduceInviteCheckFailed,
},
{
Event: user.HumanRecoveryCodesAddedType,
Reduce: p.reduceRecoveryCodesAdded,
},
{
Event: user.HumanRecoveryCodesRemovedType,
Reduce: p.reduceRecoveryCodesRemoved,
},
{
Event: user.HumanRecoveryCodeCheckSucceededType,
Reduce: p.reduceRecoveryCodeCheckSucceeded,
},
{
Event: user.HumanRecoveryCodeCheckFailedType,
Reduce: p.reduceRecoveryCodeCheckFailed,
},
},
},
}
}
func (u *userRelationalProjection) reduceHumanAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
v3Tx := v3_sql.SQLTx(tx)
userRepo := repository.UserRepository()
var phone *domain.HumanPhone
if e.PhoneNumber != "" {
phone = &domain.HumanPhone{
UnverifiedNumber: string(e.PhoneNumber),
}
}
password := domain.HumanPassword{
IsChangeRequired: e.ChangeRequired,
}
if hash := crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash); hash != "" {
password.Hash = hash
password.ChangedAt = e.CreatedAt()
}
return userRepo.Create(ctx, v3Tx, &domain.User{
InstanceID: e.Aggregate().InstanceID,
OrganizationID: e.Aggregate().ResourceOwner,
ID: e.Aggregate().ID,
Username: e.UserName,
State: domain.UserStateActive,
CreatedAt: e.CreatedAt(),
UpdatedAt: e.CreatedAt(),
// TODO check when to set username unique
// IsUsernameOrgUnique: ,
Human: &domain.HumanUser{
FirstName: e.FirstName,
LastName: e.LastName,
Nickname: e.NickName,
DisplayName: e.DisplayName,
PreferredLanguage: e.PreferredLanguage,
Gender: mapHumanGender(e.Gender),
Email: domain.HumanEmail{
UnverifiedAddress: string(e.EmailAddress),
},
Phone: phone,
Password: password,
},
})
}), nil
}
func (p *userRelationalProjection) reduceHumanRegistered(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanRegisteredEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
v3Tx := v3_sql.SQLTx(tx)
userRepo := repository.UserRepository()
var phone *domain.HumanPhone
if e.PhoneNumber != "" {
phone = &domain.HumanPhone{
UnverifiedNumber: string(e.PhoneNumber),
}
}
password := domain.HumanPassword{
IsChangeRequired: e.ChangeRequired,
}
if hash := crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash); hash != "" {
password.Hash = hash
password.ChangedAt = e.CreatedAt()
}
return userRepo.Create(ctx, v3Tx, &domain.User{
InstanceID: e.Aggregate().InstanceID,
OrganizationID: e.Aggregate().ResourceOwner,
ID: e.Aggregate().ID,
Username: e.UserName,
State: domain.UserStateActive,
CreatedAt: e.CreatedAt(),
UpdatedAt: e.CreatedAt(),
// TODO check when to set username unique
// IsUsernameOrgUnique: ,
Human: &domain.HumanUser{
FirstName: e.FirstName,
LastName: e.LastName,
Nickname: e.NickName,
DisplayName: e.DisplayName,
PreferredLanguage: e.PreferredLanguage,
Gender: mapHumanGender(e.Gender),
Email: domain.HumanEmail{
UnverifiedAddress: string(e.EmailAddress),
},
Phone: phone,
Password: password,
},
})
}), nil
}
func (p *userRelationalProjection) reduceUserLocked(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserLockedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(
ctx,
v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Agg.InstanceID, e.Aggregate().ID),
repo.SetState(domain.UserStateLocked),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceUserUnlocked(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserUnlockedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(
ctx,
v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Agg.InstanceID, e.Aggregate().ID),
repo.SetState(domain.UserStateActive),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceUserDeactivated(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserDeactivatedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(
ctx,
v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Agg.InstanceID, e.Aggregate().ID),
repo.SetState(domain.UserStateInactive),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceUserReactivated(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserReactivatedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(
ctx,
v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Agg.InstanceID, e.Aggregate().ID),
repo.SetState(domain.UserStateActive),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceUserRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Delete(
ctx,
v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Agg.InstanceID, e.Aggregate().ID),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceUsernameChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UsernameChangedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(
ctx,
v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Agg.InstanceID, e.Aggregate().ID),
repo.SetUsername(e.UserName),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceDomainClaimed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.DomainClaimedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
userRepo := repository.UserRepository()
_, err := userRepo.Update(ctx, v3_sql.SQLTx(tx),
userRepo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
userRepo.SetUsername(e.UserName),
userRepo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanProfileChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanProfileChangedEvent](event)
if err != nil {
return nil, err
}
repo := repository.UserRepository().Human()
changes := make([]database.Change, 0, 7)
if e.FirstName != "" {
changes = append(changes, repo.SetFirstName(e.FirstName))
}
if e.LastName != "" {
changes = append(changes, repo.SetLastName(e.LastName))
}
if e.NickName != nil {
changes = append(changes, repo.SetNickname(*e.NickName))
}
if e.DisplayName != nil {
changes = append(changes, repo.SetDisplayName(*e.DisplayName))
}
if e.PreferredLanguage != nil {
changes = append(changes, repo.SetPreferredLanguage(*e.PreferredLanguage))
}
if e.Gender != nil {
changes = append(changes, repo.SetGender(mapHumanGender(*e.Gender)))
}
changes = append(changes, repo.SetUpdatedAt(e.CreatedAt()))
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Agg.InstanceID, e.Aggregate().ID),
changes...,
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPhoneChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPhoneChangedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetUnverifiedPhone(string(e.PhoneNumber)),
repo.SetPhoneVerification(&domain.VerificationTypeInit{
CreatedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPhoneRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPhoneRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemovePhone(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPhoneVerified(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPhoneVerifiedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetPhoneVerification(&domain.VerificationTypeSucceeded{
VerifiedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPhoneCodeAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPhoneCodeAddedEvent](event)
if err != nil {
return nil, err
}
var expiry *time.Duration
if e.Expiry > 0 {
expiry = &e.Expiry
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetPhoneVerification(&domain.VerificationTypeUpdate{
Code: e.Code,
Expiry: expiry,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPhoneVerificationFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPhoneVerificationFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetPhoneVerification(&domain.VerificationTypeFailed{
FailedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanEmailChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanEmailChangedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetUnverifiedEmail(string(e.EmailAddress)),
repo.SetEmailVerification(&domain.VerificationTypeInit{
CreatedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanEmailVerified(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanEmailVerifiedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetEmailVerification(&domain.VerificationTypeSucceeded{
VerifiedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanEmailCodeAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanEmailCodeAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
var expiry *time.Duration
if e.Expiry > 0 {
expiry = &e.Expiry
}
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetEmailVerification(&domain.VerificationTypeUpdate{
Code: e.Code,
Expiry: expiry,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanEmailVerificationFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanEmailVerificationFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetEmailVerification(&domain.VerificationTypeFailed{
FailedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanAvatarAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanAvatarAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetAvatarKey(&e.StoreKey),
repo.SetUpdatedAt(e.CreationDate()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanAvatarRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanAvatarRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Human()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetAvatarKey(nil),
repo.SetUpdatedAt(e.CreationDate()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPasswordChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordChangedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetPasswordChangeRequired(e.ChangeRequired),
repo.SetPassword(crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)),
repo.SetResetPasswordVerification(&domain.VerificationTypeSucceeded{VerifiedAt: e.CreatedAt()}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPasswordCodeAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordCodeAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
var expiry *time.Duration
if e.Expiry > 0 {
expiry = &e.Expiry
}
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetResetPasswordVerification(&domain.VerificationTypeUpdate{
Code: e.Code,
Expiry: expiry,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPasswordCheckSucceeded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordCheckSucceededEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetLastSuccessfulPasswordCheck(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPasswordCheckFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordCheckFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.IncrementPasswordFailedAttempts(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceHumanPasswordHashUpdated(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordHashUpdatedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetPassword(e.EncodedHash),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMachineSecretSet(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MachineSecretSetEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.MachineUserRepository()
secret := crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetSecret(&secret),
repo.SetUpdatedAt(e.CreationDate()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMachineSecretHashUpdated(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MachineSecretHashUpdatedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Machine()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetSecret(&e.HashedSecret),
repo.SetUpdatedAt(e.CreationDate()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMachineSecretRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MachineSecretRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository().Machine()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetSecret(nil),
repo.SetUpdatedAt(e.CreationDate()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMachineKeyAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MachineKeyAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.MachineUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.AddKey(&domain.MachineKey{
ID: e.KeyID,
Type: mapMachineKeyType(e.KeyType),
PublicKey: e.PublicKey,
CreatedAt: e.CreatedAt(),
ExpiresAt: e.ExpirationDate,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMachineKeyRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MachineKeyRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.MachineUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveKey(e.KeyID),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMachineAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MachineAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
return repo.Create(ctx, v3_sql.SQLTx(tx),
&domain.User{
ID: e.Aggregate().ID,
InstanceID: e.Aggregate().InstanceID,
OrganizationID: e.Aggregate().ResourceOwner,
Username: e.UserName,
// TODO check when to set username unique
// IsUsernameOrgUnique: ,
State: domain.UserStateActive,
CreatedAt: e.CreatedAt(),
UpdatedAt: e.CreatedAt(),
Machine: &domain.MachineUser{
Name: e.Name,
Description: e.Description,
AccessTokenType: mapMachineAccessTokenType(e.AccessTokenType),
},
},
)
}), nil
}
func (p *userRelationalProjection) reduceMachineChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MachineChangedEvent](event)
if err != nil {
return nil, err
}
repo := repository.MachineUserRepository()
changes := make([]database.Change, 0, 4)
if e.Name != nil {
changes = append(changes, repo.SetName(*e.Name))
}
if e.Description != nil {
changes = append(changes, repo.SetDescription(*e.Description))
}
if e.AccessTokenType != nil {
changes = append(changes, repo.SetAccessTokenType(mapMachineAccessTokenType(*e.AccessTokenType)))
}
changes = append(changes, repo.SetUpdatedAt(e.CreatedAt()))
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
database.And(
repo.InstanceIDCondition(e.Aggregate().InstanceID),
repo.IDCondition(e.Aggregate().ID),
),
changes...,
)
return err
}), nil
}
func (p *userRelationalProjection) reducePersonalAccessTokenAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.PersonalAccessTokenAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.MachineUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.AddPersonalAccessToken(&domain.PersonalAccessToken{
ID: e.TokenID,
Scopes: e.Scopes,
ExpiresAt: e.Expiration,
CreatedAt: e.CreatedAt(),
}),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePersonalAccessTokenRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.PersonalAccessTokenRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.MachineUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemovePersonalAccessToken(e.TokenID),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMetadataSet(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MetadataSetEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-xg4IJ", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetMetadata(&domain.Metadata{
Key: e.Key,
Value: e.Value,
CreatedAt: e.CreationDate(),
UpdatedAt: e.CreationDate(),
}),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMetadataRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MetadataRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-xg4IJ", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveMetadata(repo.MetadataConditions().MetadataKeyCondition(database.TextOperationEqual, e.Key)),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMetadataRemovedAll(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.MetadataRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-xg4IJ", "reduce.wrong.db.pool %T", ex)
}
repo := repository.UserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveMetadata(nil),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeyAdded(event eventstore.Event) (*handler.Statement, error) {
var (
e user.HumanWebAuthNAddedEvent
typ domain.PasskeyType
)
switch typed := event.(type) {
case *user.HumanPasswordlessAddedEvent:
e = typed.HumanWebAuthNAddedEvent
typ = domain.PasskeyTypePasswordless
case *user.HumanU2FAddedEvent:
e = typed.HumanWebAuthNAddedEvent
typ = domain.PasskeyTypeU2F
default:
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-nd7f3", "reduce.wrong.event.type for passkey %s", event.Type())
}
return handler.NewStatement(&e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
database.And(
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
),
repo.AddPasskey(&domain.Passkey{
ID: e.WebAuthNTokenID,
Challenge: []byte(e.Challenge),
RelyingPartyID: e.RPID,
CreatedAt: e.CreatedAt(),
UpdatedAt: e.CreatedAt(),
Type: typ,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeyVerified(event eventstore.Event) (*handler.Statement, error) {
var (
e user.HumanWebAuthNVerifiedEvent
)
switch typed := event.(type) {
case *user.HumanPasswordlessVerifiedEvent:
e = typed.HumanWebAuthNVerifiedEvent
case *user.HumanU2FVerifiedEvent:
e = typed.HumanWebAuthNVerifiedEvent
default:
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-nd7f3", "reduce.wrong.event.type for passkey %s", event.Type())
}
return handler.NewStatement(&e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.UpdatePasskey(
repo.PasskeyConditions().IDCondition(e.WebAuthNTokenID),
repo.SetPasskeyKeyID(e.KeyID),
repo.SetPasskeyPublicKey(e.PublicKey),
repo.SetPasskeyAttestationType(e.AttestationType),
repo.SetPasskeyAuthenticatorAttestationGUID(e.AAGUID),
repo.SetPasskeySignCount(e.SignCount),
repo.SetPasskeyName(e.WebAuthNTokenName),
repo.SetPasskeyUpdatedAt(e.CreatedAt()),
),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeySignCountSet(event eventstore.Event) (*handler.Statement, error) {
var (
e user.HumanWebAuthNSignCountChangedEvent
)
switch typed := event.(type) {
case *user.HumanPasswordlessSignCountChangedEvent:
e = typed.HumanWebAuthNSignCountChangedEvent
case *user.HumanU2FSignCountChangedEvent:
e = typed.HumanWebAuthNSignCountChangedEvent
default:
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-nd7f3", "reduce.wrong.event.type for passkey %s", event.Type())
}
return handler.NewStatement(&e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.UpdatePasskey(
repo.PasskeyConditions().IDCondition(e.WebAuthNTokenID),
repo.SetPasskeySignCount(e.SignCount),
),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeyRemoved(event eventstore.Event) (*handler.Statement, error) {
var (
e user.HumanWebAuthNRemovedEvent
)
switch typed := event.(type) {
case *user.HumanPasswordlessRemovedEvent:
e = typed.HumanWebAuthNRemovedEvent
case *user.HumanU2FRemovedEvent:
e = typed.HumanWebAuthNRemovedEvent
default:
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-nd7f3", "reduce.wrong.event.type for passkey %s", event.Type())
}
return handler.NewStatement(&e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
userRepo := repository.UserRepository()
humanRepo := userRepo.Human()
_, err := userRepo.Update(ctx, v3_sql.SQLTx(tx),
userRepo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
humanRepo.RemovePasskey(humanRepo.PasskeyConditions().IDCondition(e.WebAuthNTokenID)),
humanRepo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeyInitCodeAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordlessInitCodeAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetVerification(&domain.VerificationTypeInit{
ID: &e.ID,
Code: e.Code,
CreatedAt: e.CreatedAt(),
Expiry: &e.Expiry,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeyInitCodeCheckFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordlessInitCodeCheckFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetVerification(&domain.VerificationTypeFailed{
ID: &e.ID,
FailedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeyInitCodeCheckSucceeded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordlessInitCodeCheckSucceededEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetVerification(&domain.VerificationTypeSucceeded{
ID: &e.ID,
VerifiedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reducePasskeyInitCodeRequested(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanPasswordlessInitCodeRequestedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetVerification(&domain.VerificationTypeInit{
ID: &e.ID,
Code: e.Code,
CreatedAt: e.CreatedAt(),
Expiry: &e.Expiry,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceMFAInitSkipped(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanMFAInitSkippedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SkipMultifactorInitializationAt(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceIDPLinkAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserIDPLinkAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.AddIdentityProviderLink(&domain.IdentityProviderLink{
ProviderID: e.IDPConfigID,
ProvidedUserID: e.ExternalUserID,
ProvidedUsername: e.DisplayName,
CreatedAt: e.CreatedAt(),
UpdatedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceIDPLinkCascadeRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserIDPLinkCascadeRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveIdentityProviderLink(e.IDPConfigID, e.ExternalUserID),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceIDPLinkRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserIDPLinkRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveIdentityProviderLink(e.IDPConfigID, e.ExternalUserID),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceIDPLinkUserIDMigrated(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserIDPExternalIDMigratedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.UpdateIdentityProviderLink(
database.And(repo.IdentityProviderLinkConditions().ProviderIDCondition(e.IDPConfigID), repo.IdentityProviderLinkConditions().ProvidedUserIDCondition(e.PreviousID)),
repo.SetIdentityProviderLinkProvidedID(e.NewID),
),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceIDPLinkUsernameChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.UserIDPExternalUsernameEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.UpdateIdentityProviderLink(
database.And(repo.IdentityProviderLinkConditions().ProviderIDCondition(e.IDPConfigID), repo.IdentityProviderLinkConditions().ProvidedUserIDCondition(e.ExternalUserID)),
repo.SetIdentityProviderLinkUsername(e.ExternalUsername),
),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceTOTPAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetTOTPSecret(e.Secret),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceTOTPVerified(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPVerifiedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetTOTPVerifiedAt(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceTOTPRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveTOTP(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceTOTPCheckSucceeded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPCheckSucceededEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetLastSuccessfulTOTPCheck(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceTOTPCheckFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPCheckFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.IncrementTOTPFailedAttempts(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPSMSEnabled(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPSMSAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.EnableSMSOTPAt(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPSMSDisabled(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPSMSRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.DisableSMSOTP(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPSMSCheckSucceeded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPSMSCheckSucceededEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetLastSuccessfulSMSOTPCheck(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPSMSCheckFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPSMSCheckFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.IncrementSMSOTPFailedAttempts(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPEmailEnabled(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPEmailAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.EnableEmailOTPAt(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPEmailDisabled(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPEmailRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.DisableEmailOTP(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPEmailCheckSucceeded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPEmailCheckSucceededEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetLastSuccessfulEmailOTPCheck(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceOTPEmailCheckFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanOTPEmailCheckFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.IncrementEmailOTPFailedAttempts(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceInviteCodeAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanInviteCodeAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
var expiry *time.Duration
if e.Expiry > 0 {
expiry = &e.Expiry
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetInviteVerification(&domain.VerificationTypeInit{
CreatedAt: e.CreatedAt(),
Code: e.Code,
Expiry: expiry,
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceInviteCheckSucceeded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanInviteCheckSucceededEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetInviteVerification(&domain.VerificationTypeSucceeded{
VerifiedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceInviteCheckFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanInviteCheckFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-iZGH3", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.SetInviteVerification(&domain.VerificationTypeFailed{
FailedAt: e.CreatedAt(),
}),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceRecoveryCodesAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanRecoveryCodesAddedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-oqwfuV", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.AddRecoveryCodes(e.Codes),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceRecoveryCodesRemoved(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanRecoveryCodesRemovedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-ZueNKs", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveAllRecoveryCodes(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceRecoveryCodeCheckSucceeded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanRecoveryCodeCheckSucceededEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-wr8WuW", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.RemoveRecoveryCode(e.CodeChecked),
repo.SetLastSuccessfulRecoveryCodeCheck(e.CreatedAt()),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func (p *userRelationalProjection) reduceRecoveryCodeCheckFailed(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*user.HumanRecoveryCodeCheckFailedEvent](event)
if err != nil {
return nil, err
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-mWuV7a", "reduce.wrong.db.pool %T", ex)
}
repo := repository.HumanUserRepository()
_, err := repo.Update(ctx, v3_sql.SQLTx(tx),
repo.PrimaryKeyCondition(e.Aggregate().InstanceID, e.Aggregate().ID),
repo.IncrementRecoveryCodeFailedAttempts(),
repo.SetUpdatedAt(e.CreatedAt()),
)
return err
}), nil
}
func mapHumanGender(gender old_domain.Gender) domain.HumanGender {
switch gender {
case old_domain.GenderFemale:
return domain.HumanGenderFemale
case old_domain.GenderMale:
return domain.HumanGenderMale
case old_domain.GenderDiverse:
return domain.HumanGenderDiverse
case old_domain.GenderUnspecified:
fallthrough
default:
return domain.HumanGenderUnspecified
}
}
func mapMachineAccessTokenType(tokenType old_domain.OIDCTokenType) domain.AccessTokenType {
switch tokenType {
case old_domain.OIDCTokenTypeBearer:
return domain.AccessTokenTypeBearer
case old_domain.OIDCTokenTypeJWT:
return domain.AccessTokenTypeJWT
default:
return domain.AccessTokenTypeUnspecified
}
}
func mapMachineKeyType(keyType old_domain.AuthNKeyType) domain.MachineKeyType {
switch keyType {
case old_domain.AuthNKeyTypeJSON:
return domain.MachineKeyTypeJSON
case old_domain.AuthNKeyTypeNONE:
fallthrough
default:
return domain.MachineKeyTypeNone
}
}