2025-04-29 06:03:47 +02:00
package domain
import (
"context"
"github.com/zitadel/zitadel/backend/v3/storage/eventstore"
)
2025-05-08 19:01:55 +02:00
// CreateUserCommand adds a new user including the email verification for humans.
// In the future it might make sense to separate the command into two commands:
// - CreateHumanCommand: creates a new human user
// - CreateMachineCommand: creates a new machine user
2025-04-29 06:03:47 +02:00
type CreateUserCommand struct {
user * User
email * SetEmailCommand
}
var (
_ Commander = ( * CreateUserCommand ) ( nil )
_ eventer = ( * CreateUserCommand ) ( nil )
)
2025-05-08 19:01:55 +02:00
// opts heavily reduces the complexity for email verification because each type of verification is a simple option which implements the [Commander] interface.
2025-04-29 06:03:47 +02:00
func NewCreateHumanCommand ( username string , opts ... CreateHumanOpt ) * CreateUserCommand {
cmd := & CreateUserCommand {
user : & User {
2025-05-06 07:18:11 +02:00
Username : username ,
Traits : & Human { } ,
2025-04-29 06:03:47 +02:00
} ,
}
for _ , opt := range opts {
opt . applyOnCreateHuman ( cmd )
}
return cmd
}
2025-05-08 15:30:06 +02:00
// String implements [Commander].
func ( cmd * CreateUserCommand ) String ( ) string {
return "CreateUserCommand"
}
2025-04-29 06:03:47 +02:00
// Events implements [eventer].
func ( c * CreateUserCommand ) Events ( ) [ ] * eventstore . Event {
2025-05-08 15:30:06 +02:00
return [ ] * eventstore . Event {
{
AggregateType : "user" ,
AggregateID : c . user . ID ,
Type : "user.added" ,
Payload : c . user ,
} ,
}
2025-04-29 06:03:47 +02:00
}
// Execute implements [Commander].
func ( c * CreateUserCommand ) Execute ( ctx context . Context , opts * CommandOpts ) error {
if err := c . ensureUserID ( ) ; err != nil {
return err
}
c . email . UserID = c . user . ID
if err := opts . Invoke ( ctx , c . email ) ; err != nil {
return err
}
return nil
}
type CreateHumanOpt interface {
applyOnCreateHuman ( * CreateUserCommand )
}
type createHumanIDOpt string
// applyOnCreateHuman implements [CreateHumanOpt].
func ( c createHumanIDOpt ) applyOnCreateHuman ( cmd * CreateUserCommand ) {
cmd . user . ID = string ( c )
}
var _ CreateHumanOpt = ( * createHumanIDOpt ) ( nil )
func CreateHumanWithID ( id string ) CreateHumanOpt {
return createHumanIDOpt ( id )
}
func ( c * CreateUserCommand ) ensureUserID ( ) ( err error ) {
if c . user . ID != "" {
return nil
}
c . user . ID , err = generateID ( )
return err
}