Files
zitadel/backend/v3/storage/database/repository/user_invite.go
T
5df8a97f9d feat(repository): implement user repository (#10967)
## Summary

This PR introduces the relational user repository for backend v3,
including schema, repository APIs, reducers/projections, and tests for
both human and machine users.

## What changed

* Added user-focused relational migrations (users, verifications,
metadata, PATs, machine keys, passkeys, identity provider links) and
related FK wiring.
* Implemented/expanded repository domain contracts and storage
implementations for human and machine user flows.
* Added support for machine secret handling and aligned access token
type modeling.
* Extended user domain models (verifications, password/email/phone/TOTP
state, passkeys, metadata, invite handling, identity provider links).
* Updated projection/reduction coverage and integration tests for key
user lifecycle events.
* Regenerated and updated mocks/enums plus supporting database
change/column utilities.

## Notes for reviewers

* This PR is large because it establishes the foundational relational
user storage layer and related test scaffolding. Sorry for that.

## Closes

Closes #10218
Closes #10224
Closes #10225
Closes #10209
Closes #10802

---------

Co-authored-by: Iraq Jaber <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
2026-02-23 16:03:47 +01:00

50 lines
2.1 KiB
Go

package repository
import (
"fmt"
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
)
// -------------------------------------------------------------
// changes
// -------------------------------------------------------------
// SetInviteVerification implements [domain.HumanUserRepository].
func (u userHuman) SetInviteVerification(verification domain.VerificationType) database.Change {
switch typ := verification.(type) {
case *domain.VerificationTypeInit:
return u.verification.init(typ, existingUser.unqualifiedTableName(), existingHumanUser.inviteVerificationIDColumn())
case *domain.VerificationTypeUpdate:
return u.verification.update(typ, existingHumanUser.unqualifiedTableName(),
existingHumanUser.InstanceIDColumn(), existingHumanUser.inviteVerificationIDColumn(),
)
case *domain.VerificationTypeSucceeded:
return u.verification.verified(typ, existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(),
existingHumanUser.inviteVerificationIDColumn(), u.inviteAcceptedAtColumn(), u.failedInviteAttemptsColumn(),
)
case *domain.VerificationTypeSkipped:
return u.verification.skipped(typ, u.inviteAcceptedAtColumn(), u.inviteVerificationIDColumn(), u.failedInviteAttemptsColumn())
case *domain.VerificationTypeFailed:
return u.verification.failed(existingHumanUser.unqualifiedTableName(), existingHumanUser.InstanceIDColumn(), existingHumanUser.inviteVerificationIDColumn())
}
panic(fmt.Sprintf("undefined verification type %T", verification))
}
// -------------------------------------------------------------
// columns
// -------------------------------------------------------------
func (u userHuman) inviteVerificationIDColumn() database.Column {
return database.NewColumn(u.unqualifiedTableName(), "invite_verification_id")
}
func (u userHuman) inviteAcceptedAtColumn() database.Column {
return database.NewColumn(u.unqualifiedTableName(), "invite_accepted_at")
}
func (u userHuman) failedInviteAttemptsColumn() database.Column {
return database.NewColumn(u.unqualifiedTableName(), "invite_failed_attempts")
}