zitadel/internal/command/user_v3_model.go
Stefan Benz 41ae35f2ef
feat: add schema user create and remove (#8494)
# Which Problems Are Solved

Added functionality that user with a userschema can be created and
removed.

# How the Problems Are Solved

Added logic and moved APIs so that everything is API v3 conform.

# Additional Changes

- move of user and userschema API to resources folder
- changed testing and parameters
- some renaming

# Additional Context

closes #7308

---------

Co-authored-by: Elio Bischof <elio@zitadel.com>
2024-08-28 19:46:45 +00:00

175 lines
4.4 KiB
Go

package command
import (
"bytes"
"context"
"encoding/json"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/user/schemauser"
)
type UserV3WriteModel struct {
eventstore.WriteModel
PhoneWM bool
EmailWM bool
DataWM bool
SchemaID string
SchemaRevision uint64
Email string
IsEmailVerified bool
EmailVerifiedFailedCount int
Phone string
IsPhoneVerified bool
PhoneVerifiedFailedCount int
Data json.RawMessage
State domain.UserState
}
func NewExistsUserV3WriteModel(resourceOwner, userID string) *UserV3WriteModel {
return &UserV3WriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: userID,
ResourceOwner: resourceOwner,
},
PhoneWM: false,
EmailWM: false,
DataWM: false,
}
}
func NewUserV3WriteModel(resourceOwner, userID string) *UserV3WriteModel {
return &UserV3WriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: userID,
ResourceOwner: resourceOwner,
},
PhoneWM: true,
EmailWM: true,
DataWM: true,
}
}
func (wm *UserV3WriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *schemauser.CreatedEvent:
wm.SchemaID = e.SchemaID
wm.SchemaRevision = 1
wm.Data = e.Data
wm.State = domain.UserStateActive
case *schemauser.UpdatedEvent:
if e.SchemaID != nil {
wm.SchemaID = *e.SchemaID
}
if e.SchemaRevision != nil {
wm.SchemaRevision = *e.SchemaRevision
}
if len(e.Data) > 0 {
wm.Data = e.Data
}
case *schemauser.DeletedEvent:
wm.State = domain.UserStateDeleted
case *schemauser.EmailUpdatedEvent:
wm.Email = string(e.EmailAddress)
case *schemauser.EmailCodeAddedEvent:
wm.IsEmailVerified = false
wm.EmailVerifiedFailedCount = 0
case *schemauser.EmailVerifiedEvent:
wm.IsEmailVerified = true
wm.EmailVerifiedFailedCount = 0
case *schemauser.EmailVerificationFailedEvent:
wm.EmailVerifiedFailedCount += 1
case *schemauser.PhoneChangedEvent:
wm.Phone = string(e.PhoneNumber)
case *schemauser.PhoneCodeAddedEvent:
wm.IsPhoneVerified = false
wm.PhoneVerifiedFailedCount = 0
case *schemauser.PhoneVerifiedEvent:
wm.PhoneVerifiedFailedCount = 0
wm.IsPhoneVerified = true
case *schemauser.PhoneVerificationFailedEvent:
wm.PhoneVerifiedFailedCount += 1
}
}
return wm.WriteModel.Reduce()
}
func (wm *UserV3WriteModel) Query() *eventstore.SearchQueryBuilder {
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
ResourceOwner(wm.ResourceOwner).
AddQuery().
AggregateTypes(schemauser.AggregateType).
AggregateIDs(wm.AggregateID).
EventTypes(
schemauser.CreatedType,
schemauser.DeletedType,
)
if wm.DataWM {
query = query.EventTypes(
schemauser.UpdatedType,
)
}
if wm.EmailWM {
query = query.EventTypes(
schemauser.EmailUpdatedType,
schemauser.EmailVerifiedType,
schemauser.EmailCodeAddedType,
schemauser.EmailVerificationFailedType,
)
}
if wm.PhoneWM {
query = query.EventTypes(
schemauser.PhoneUpdatedType,
schemauser.PhoneVerifiedType,
schemauser.PhoneCodeAddedType,
schemauser.PhoneVerificationFailedType,
)
}
return query.Builder()
}
func (wm *UserV3WriteModel) NewUpdatedEvent(
ctx context.Context,
agg *eventstore.Aggregate,
schemaID *string,
schemaRevision *uint64,
data json.RawMessage,
) *schemauser.UpdatedEvent {
changes := make([]schemauser.Changes, 0)
if schemaID != nil && wm.SchemaID != *schemaID {
changes = append(changes, schemauser.ChangeSchemaID(wm.SchemaID, *schemaID))
}
if schemaRevision != nil && wm.SchemaRevision != *schemaRevision {
changes = append(changes, schemauser.ChangeSchemaRevision(wm.SchemaRevision, *schemaRevision))
}
if !bytes.Equal(wm.Data, data) {
changes = append(changes, schemauser.ChangeData(data))
}
if len(changes) == 0 {
return nil
}
return schemauser.NewUpdatedEvent(ctx, agg, changes)
}
func UserV3AggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
return &eventstore.Aggregate{
ID: wm.AggregateID,
Type: schemauser.AggregateType,
ResourceOwner: wm.ResourceOwner,
InstanceID: wm.InstanceID,
Version: schemauser.AggregateVersion,
}
}
func (wm *UserV3WriteModel) Exists() bool {
return wm.State != domain.UserStateDeleted && wm.State != domain.UserStateUnspecified
}