mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
## 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]>
104 lines
3.5 KiB
Go
104 lines
3.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/zitadel/zitadel/backend/v3/domain"
|
|
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
|
)
|
|
|
|
type userMachine struct {
|
|
user
|
|
machineKey
|
|
userPersonalAccessToken
|
|
}
|
|
|
|
func (u userMachine) create(ctx context.Context, builder *database.StatementBuilder, client database.QueryExecutor, user *domain.User) error {
|
|
changes := make(database.Changes, 0, len(user.Machine.Keys)+len(user.Machine.PATs))
|
|
for _, key := range user.Machine.Keys {
|
|
changes = append(changes, u.AddKey(key))
|
|
}
|
|
for _, pat := range user.Machine.PATs {
|
|
changes = append(changes, u.AddPersonalAccessToken(pat))
|
|
}
|
|
for _, metadata := range user.Metadata {
|
|
changes = append(changes, u.SetMetadata(metadata))
|
|
}
|
|
for i, change := range changes {
|
|
sessionCTE(change, i, 0, builder)
|
|
}
|
|
|
|
builder.WriteString("INSERT INTO zitadel.users (" +
|
|
"instance_id, organization_id, id, username, state, type" +
|
|
", name, description, secret, access_token_type, created_at, updated_at) VALUES (",
|
|
)
|
|
|
|
var createdAt any = database.NowInstruction
|
|
if !user.CreatedAt.IsZero() {
|
|
createdAt = user.CreatedAt
|
|
}
|
|
builder.WriteArgs(
|
|
user.InstanceID, user.OrganizationID, user.ID, user.Username, user.State, "machine",
|
|
user.Machine.Name, user.Machine.Description, user.Machine.Secret, uint8(user.Machine.AccessTokenType),
|
|
createdAt, createdAt,
|
|
)
|
|
|
|
builder.WriteString(") RETURNING created_at, updated_at")
|
|
|
|
return client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&user.CreatedAt, &user.UpdatedAt)
|
|
}
|
|
|
|
// Update implements [domain.MachineUserRepository].
|
|
func (u userMachine) Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error) {
|
|
if !condition.IsRestrictingColumn(u.TypeColumn()) {
|
|
condition = database.And(condition, u.TypeCondition(domain.UserTypeMachine))
|
|
}
|
|
return u.user.Update(ctx, client, condition, changes...)
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// changes
|
|
// -------------------------------------------------------------
|
|
|
|
// SetAccessTokenType implements [domain.MachineUserRepository].
|
|
func (u userMachine) SetAccessTokenType(tokenType domain.AccessTokenType) database.Change {
|
|
return database.NewChange(u.accessTokenTypeColumn(), tokenType)
|
|
}
|
|
|
|
// SetDescription implements [domain.MachineUserRepository].
|
|
func (u userMachine) SetDescription(description string) database.Change {
|
|
return database.NewChange(u.descriptionColumn(), description)
|
|
}
|
|
|
|
// SetName implements [domain.MachineUserRepository].
|
|
func (u userMachine) SetName(name string) database.Change {
|
|
return database.NewChange(u.nameColumn(), name)
|
|
}
|
|
|
|
// SetSecret implements [domain.MachineUserRepository].
|
|
func (u userMachine) SetSecret(secret *string) database.Change {
|
|
return database.NewChangePtr(u.secretColumn(), secret)
|
|
}
|
|
|
|
var _ domain.MachineUserRepository = (*userMachine)(nil)
|
|
|
|
// -------------------------------------------------------------
|
|
// columns
|
|
// -------------------------------------------------------------
|
|
|
|
func (u userMachine) nameColumn() database.Column {
|
|
return database.NewColumn(u.user.unqualifiedTableName(), "name")
|
|
}
|
|
|
|
func (u userMachine) descriptionColumn() database.Column {
|
|
return database.NewColumn(u.user.unqualifiedTableName(), "description")
|
|
}
|
|
|
|
func (u userMachine) accessTokenTypeColumn() database.Column {
|
|
return database.NewColumn(u.user.unqualifiedTableName(), "access_token_type")
|
|
}
|
|
|
|
func (u userMachine) secretColumn() database.Column {
|
|
return database.NewColumn(u.user.unqualifiedTableName(), "secret")
|
|
}
|