fix: setup instance domain handling (#3529)

This commit is contained in:
Livio Amstutz 2022-04-28 10:30:41 +02:00 committed by GitHub
parent 70e98460ab
commit 00f7dbe875
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 152 additions and 113 deletions

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"strings"
"github.com/zitadel/zitadel/internal/api/authz" "github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/command"
@ -14,15 +15,18 @@ import (
) )
type DefaultInstance struct { type DefaultInstance struct {
InstanceSetup command.InstanceSetup InstanceName string
CustomDomain string
Org command.OrgSetup
instanceSetup command.InstanceSetup
userEncryptionKey *crypto.KeyConfig userEncryptionKey *crypto.KeyConfig
masterKey string masterKey string
db *sql.DB db *sql.DB
es *eventstore.Eventstore es *eventstore.Eventstore
domain string
defaults systemdefaults.SystemDefaults defaults systemdefaults.SystemDefaults
zitadelRoles []authz.RoleMapping zitadelRoles []authz.RoleMapping
externalDomain string
externalSecure bool externalSecure bool
externalPort uint16 externalPort uint16
} }
@ -47,6 +51,7 @@ func (mig *DefaultInstance) Execute(ctx context.Context) error {
nil, nil,
nil, nil,
nil, nil,
mig.externalDomain,
mig.externalSecure, mig.externalSecure,
mig.externalPort, mig.externalPort,
nil, nil,
@ -60,9 +65,16 @@ func (mig *DefaultInstance) Execute(ctx context.Context) error {
if err != nil { if err != nil {
return err return err
} }
ctx = authz.WithRequestedDomain(ctx, mig.domain)
_, _, err = cmd.SetUpInstance(ctx, &mig.InstanceSetup, mig.externalSecure) mig.instanceSetup.InstanceName = mig.InstanceName
mig.instanceSetup.CustomDomain = mig.CustomDomain
mig.instanceSetup.Org = mig.Org
mig.instanceSetup.Org.Human.Email.Address = strings.TrimSpace(mig.instanceSetup.Org.Human.Email.Address)
if mig.instanceSetup.Org.Human.Email.Address == "" {
mig.instanceSetup.Org.Human.Email.Address = "admin@" + mig.instanceSetup.CustomDomain
}
_, _, err = cmd.SetUpInstance(ctx, &mig.instanceSetup)
return err return err
} }

View File

@ -19,6 +19,7 @@ type Config struct {
Database database.Config Database database.Config
SystemDefaults systemdefaults.SystemDefaults SystemDefaults systemdefaults.SystemDefaults
InternalAuthZ authz.Config InternalAuthZ authz.Config
ExternalDomain string
ExternalPort uint16 ExternalPort uint16
ExternalSecure bool ExternalSecure bool
Log *logging.Config Log *logging.Config

View File

@ -3,7 +3,6 @@ package setup
import ( import (
"context" "context"
_ "embed" _ "embed"
"strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -60,24 +59,14 @@ func Setup(config *Config, steps *Steps, masterKey string) {
steps.s1ProjectionTable = &ProjectionTable{dbClient: dbClient} steps.s1ProjectionTable = &ProjectionTable{dbClient: dbClient}
steps.s2AssetsTable = &AssetTable{dbClient: dbClient} steps.s2AssetsTable = &AssetTable{dbClient: dbClient}
instanceSetup := config.DefaultInstance steps.S3DefaultInstance.instanceSetup = config.DefaultInstance
instanceSetup.InstanceName = steps.S3DefaultInstance.InstanceSetup.InstanceName
instanceSetup.CustomDomain = steps.S3DefaultInstance.InstanceSetup.CustomDomain
instanceSetup.Org = steps.S3DefaultInstance.InstanceSetup.Org
steps.S3DefaultInstance.InstanceSetup = instanceSetup
steps.S3DefaultInstance.InstanceSetup.Org.Human.Email.Address = strings.TrimSpace(steps.S3DefaultInstance.InstanceSetup.Org.Human.Email.Address)
if steps.S3DefaultInstance.InstanceSetup.Org.Human.Email.Address == "" {
steps.S3DefaultInstance.InstanceSetup.Org.Human.Email.Address = "admin@" + instanceSetup.CustomDomain
}
steps.S3DefaultInstance.es = eventstoreClient
steps.S3DefaultInstance.db = dbClient
steps.S3DefaultInstance.defaults = config.SystemDefaults
steps.S3DefaultInstance.masterKey = masterKey
steps.S3DefaultInstance.domain = instanceSetup.CustomDomain
steps.S3DefaultInstance.zitadelRoles = config.InternalAuthZ.RolePermissionMappings
steps.S3DefaultInstance.userEncryptionKey = config.EncryptionKeys.User steps.S3DefaultInstance.userEncryptionKey = config.EncryptionKeys.User
steps.S3DefaultInstance.masterKey = masterKey
steps.S3DefaultInstance.db = dbClient
steps.S3DefaultInstance.es = eventstoreClient
steps.S3DefaultInstance.defaults = config.SystemDefaults
steps.S3DefaultInstance.zitadelRoles = config.InternalAuthZ.RolePermissionMappings
steps.S3DefaultInstance.externalDomain = config.ExternalDomain
steps.S3DefaultInstance.externalSecure = config.ExternalSecure steps.S3DefaultInstance.externalSecure = config.ExternalSecure
steps.S3DefaultInstance.externalPort = config.ExternalPort steps.S3DefaultInstance.externalPort = config.ExternalPort
@ -85,9 +74,9 @@ func Setup(config *Config, steps *Steps, masterKey string) {
err = migration.Migrate(ctx, eventstoreClient, steps.s1ProjectionTable) err = migration.Migrate(ctx, eventstoreClient, steps.s1ProjectionTable)
logging.OnError(err).Fatal("unable to migrate step 1") logging.OnError(err).Fatal("unable to migrate step 1")
err = migration.Migrate(ctx, eventstoreClient, steps.s2AssetsTable) err = migration.Migrate(ctx, eventstoreClient, steps.s2AssetsTable)
logging.OnError(err).Fatal("unable to migrate step 3") logging.OnError(err).Fatal("unable to migrate step 2")
err = migration.Migrate(ctx, eventstoreClient, steps.S3DefaultInstance) err = migration.Migrate(ctx, eventstoreClient, steps.S3DefaultInstance)
logging.OnError(err).Fatal("unable to migrate step 4") logging.OnError(err).Fatal("unable to migrate step 3")
} }
func initSteps(v *viper.Viper, files ...string) func() { func initSteps(v *viper.Viper, files ...string) func() {

View File

@ -1,21 +1,21 @@
S3DefaultInstance: S3DefaultInstance:
InstanceSetup: InstanceName: Localhost
InstanceName: Localhost CustomDomain: localhost
CustomDomain: localhost Org:
Org: Name: ZITADEL
Name: ZITADEL Human:
Human: UserName: zitadel-admin
UserName: zitadel-admin FirstName: ZITADEL
FirstName: ZITADEL LastName: Admin
LastName: Admin NickName:
NickName: DisplayName:
DisplayName: Email:
Email: Address: #autogenerated if empty. uses domain from config and prefixes admin@. for example: admin@domain.tdl
Address: #autogenerated if empty. uses domain from config and prefixes admin@. for example: admin@domain.tdl Verified: true
Verified: true PreferredLanguage: en
PreferredLanguage: Gender:
Gender: Phone:
Phone: Number:
Number: Verified:
Verified: Password: Password1!
Password: Password1! PasswordChangeRequired: true

View File

@ -28,6 +28,7 @@ type Config struct {
Log *logging.Config Log *logging.Config
Port uint16 Port uint16
ExternalPort uint16 ExternalPort uint16
ExternalDomain string
ExternalSecure bool ExternalSecure bool
HTTP2HostHeader string HTTP2HostHeader string
HTTP1HostHeader string HTTP1HostHeader string

View File

@ -118,6 +118,7 @@ func startZitadel(config *Config, masterKey string) error {
storage, storage,
authZRepo, authZRepo,
webAuthNConfig, webAuthNConfig,
config.ExternalDomain,
config.ExternalSecure, config.ExternalSecure,
config.ExternalPort, config.ExternalPort,
keys.IDPConfig, keys.IDPConfig,
@ -161,7 +162,7 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
if err != nil { if err != nil {
return fmt.Errorf("error starting admin repo: %w", err) return fmt.Errorf("error starting admin repo: %w", err)
} }
if err := authenticatedAPIs.RegisterServer(ctx, system.CreateServer(commands, queries, adminRepo, config.DefaultInstance, config.ExternalSecure)); err != nil { if err := authenticatedAPIs.RegisterServer(ctx, system.CreateServer(commands, queries, adminRepo, config.DefaultInstance)); err != nil {
return err return err
} }
if err := authenticatedAPIs.RegisterServer(ctx, admin.CreateServer(commands, queries, adminRepo, assets.HandlerPrefix, keys.User)); err != nil { if err := authenticatedAPIs.RegisterServer(ctx, admin.CreateServer(commands, queries, adminRepo, assets.HandlerPrefix, keys.User)); err != nil {

View File

@ -5,6 +5,7 @@ Log:
Port: 8080 Port: 8080
ExternalPort: 8080 ExternalPort: 8080
ExternalDomain: #must be provided
ExternalSecure: true ExternalSecure: true
HTTP2HostHeader: ":authority" HTTP2HostHeader: ":authority"
HTTP1HostHeader: "host" HTTP1HostHeader: "host"
@ -172,7 +173,7 @@ DefaultInstance:
Email: Email:
Address: Address:
Verified: false Verified: false
PreferredLanguage: PreferredLanguage: en
Gender: Gender:
Phone: Phone:
Number: Number:

View File

@ -14,16 +14,16 @@ func setUpOrgHumanToCommand(human *admin_grpc.SetUpOrgRequest_Human) command.Add
lang, err := language.Parse(human.Profile.PreferredLanguage) lang, err := language.Parse(human.Profile.PreferredLanguage)
logging.OnError(err).Debug("unable to parse language") logging.OnError(err).Debug("unable to parse language")
return command.AddHuman{ return command.AddHuman{
Username: human.UserName, Username: human.UserName,
FirstName: human.Profile.FirstName, FirstName: human.Profile.FirstName,
LastName: human.Profile.LastName, LastName: human.Profile.LastName,
NickName: human.Profile.NickName, NickName: human.Profile.NickName,
DisplayName: human.Profile.DisplayName, DisplayName: human.Profile.DisplayName,
PreferredLang: lang, PreferredLanguage: lang,
Gender: user_grpc.GenderToDomain(human.Profile.Gender), Gender: user_grpc.GenderToDomain(human.Profile.Gender),
Email: setUpOrgHumanEmailToDomain(human.Email), Email: setUpOrgHumanEmailToDomain(human.Email),
Phone: setUpOrgHumanPhoneToDomain(human.Phone), Phone: setUpOrgHumanPhoneToDomain(human.Phone),
Password: human.Password, Password: human.Password,
} }
} }

View File

@ -209,12 +209,8 @@ func (s *Server) AddHumanUser(ctx context.Context, req *mgmt_pb.AddHumanUserRequ
Address: req.Email.Email, Address: req.Email.Email,
Verified: req.Email.IsEmailVerified, Verified: req.Email.IsEmailVerified,
}, },
PreferredLang: lang, PreferredLanguage: lang,
Gender: user_grpc.GenderToDomain(req.Profile.Gender), Gender: user_grpc.GenderToDomain(req.Profile.Gender),
Phone: command.Phone{
Number: req.Phone.Phone,
Verified: req.Phone.IsPhoneVerified,
},
Password: req.InitialPassword, Password: req.InitialPassword,
PasswordChangeRequired: true, PasswordChangeRequired: true,
Passwordless: false, Passwordless: false,

View File

@ -41,7 +41,7 @@ func (s *Server) GetInstance(ctx context.Context, req *system_pb.GetInstanceRequ
} }
func (s *Server) AddInstance(ctx context.Context, req *system_pb.AddInstanceRequest) (*system_pb.AddInstanceResponse, error) { func (s *Server) AddInstance(ctx context.Context, req *system_pb.AddInstanceRequest) (*system_pb.AddInstanceResponse, error) {
id, details, err := s.command.SetUpInstance(ctx, AddInstancePbToSetupInstance(req, s.DefaultInstance), s.ExternalSecure) id, details, err := s.command.SetUpInstance(ctx, AddInstancePbToSetupInstance(req, s.DefaultInstance))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,13 +1,14 @@
package system package system
import ( import (
"golang.org/x/text/language"
instance_grpc "github.com/zitadel/zitadel/internal/api/grpc/instance" instance_grpc "github.com/zitadel/zitadel/internal/api/grpc/instance"
"github.com/zitadel/zitadel/internal/api/grpc/object" "github.com/zitadel/zitadel/internal/api/grpc/object"
"github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/query" "github.com/zitadel/zitadel/internal/query"
instance_pb "github.com/zitadel/zitadel/pkg/grpc/instance" instance_pb "github.com/zitadel/zitadel/pkg/grpc/instance"
system_pb "github.com/zitadel/zitadel/pkg/grpc/system" system_pb "github.com/zitadel/zitadel/pkg/grpc/system"
"golang.org/x/text/language"
) )
func AddInstancePbToSetupInstance(req *system_pb.AddInstanceRequest, defaultInstance command.InstanceSetup) *command.InstanceSetup { func AddInstancePbToSetupInstance(req *system_pb.AddInstanceRequest, defaultInstance command.InstanceSetup) *command.InstanceSetup {
@ -35,7 +36,7 @@ func AddInstancePbToSetupInstance(req *system_pb.AddInstanceRequest, defaultInst
if req.OwnerProfile.PreferredLanguage != "" { if req.OwnerProfile.PreferredLanguage != "" {
lang, err := language.Parse(req.OwnerProfile.PreferredLanguage) lang, err := language.Parse(req.OwnerProfile.PreferredLanguage)
if err == nil { if err == nil {
defaultInstance.Org.Human.PreferredLang = lang defaultInstance.Org.Human.PreferredLanguage = lang
} }
} }
} }

View File

@ -25,7 +25,6 @@ type Server struct {
query *query.Queries query *query.Queries
administrator repository.AdministratorRepository administrator repository.AdministratorRepository
DefaultInstance command.InstanceSetup DefaultInstance command.InstanceSetup
ExternalSecure bool
} }
type Config struct { type Config struct {
@ -36,13 +35,12 @@ func CreateServer(command *command.Commands,
query *query.Queries, query *query.Queries,
repo repository.Repository, repo repository.Repository,
defaultInstance command.InstanceSetup, defaultInstance command.InstanceSetup,
externalSecure bool) *Server { ) *Server {
return &Server{ return &Server{
command: command, command: command,
query: query, query: query,
administrator: repo, administrator: repo,
DefaultInstance: defaultInstance, DefaultInstance: defaultInstance,
ExternalSecure: externalSecure,
} }
} }

View File

@ -10,6 +10,7 @@ import (
sd "github.com/zitadel/zitadel/internal/config/systemdefaults" sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
"github.com/zitadel/zitadel/internal/crypto" "github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/id" "github.com/zitadel/zitadel/internal/id"
"github.com/zitadel/zitadel/internal/repository/action" "github.com/zitadel/zitadel/internal/repository/action"
@ -28,6 +29,7 @@ type Commands struct {
static static.Storage static static.Storage
idGenerator id.Generator idGenerator id.Generator
zitadelRoles []authz.RoleMapping zitadelRoles []authz.RoleMapping
externalDomain string
externalSecure bool externalSecure bool
externalPort uint16 externalPort uint16
@ -62,6 +64,7 @@ func StartCommands(es *eventstore.Eventstore,
staticStore static.Storage, staticStore static.Storage,
authZRepo authz_repo.Repository, authZRepo authz_repo.Repository,
webAuthN *webauthn_helper.Config, webAuthN *webauthn_helper.Config,
externalDomain string,
externalSecure bool, externalSecure bool,
externalPort uint16, externalPort uint16,
idpConfigEncryption, idpConfigEncryption,
@ -72,11 +75,15 @@ func StartCommands(es *eventstore.Eventstore,
domainVerificationEncryption, domainVerificationEncryption,
oidcEncryption crypto.EncryptionAlgorithm, oidcEncryption crypto.EncryptionAlgorithm,
) (repo *Commands, err error) { ) (repo *Commands, err error) {
if externalDomain == "" {
return nil, errors.ThrowInvalidArgument(nil, "COMMAND-Df21s", "not external domain specified")
}
repo = &Commands{ repo = &Commands{
eventstore: es, eventstore: es,
static: staticStore, static: staticStore,
idGenerator: id.SonyFlakeGenerator, idGenerator: id.SonyFlakeGenerator,
zitadelRoles: zitadelRoles, zitadelRoles: zitadelRoles,
externalDomain: externalDomain,
externalSecure: externalSecure, externalSecure: externalSecure,
externalPort: externalPort, externalPort: externalPort,
keySize: defaults.KeyConfig.Size, keySize: defaults.KeyConfig.Size,

View File

@ -157,7 +157,7 @@ func (s *InstanceSetup) generateIDs() (err error) {
return nil return nil
} }
func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup, externalSecure bool) (string, *domain.ObjectDetails, error) { func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (string, *domain.ObjectDetails, error) {
instanceID, err := id.SonyFlakeGenerator.Next() instanceID, err := id.SonyFlakeGenerator.Next()
if err != nil { if err != nil {
return "", nil, err return "", nil, err
@ -167,8 +167,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup, exte
return "", nil, err return "", nil, err
} }
requestedDomain := authz.GetInstance(ctx).RequestedDomain() ctx = authz.SetCtxData(authz.WithRequestedDomain(authz.WithInstanceID(ctx, instanceID), c.externalDomain), authz.CtxData{OrgID: instanceID, ResourceOwner: instanceID})
ctx = authz.SetCtxData(authz.WithRequestedDomain(authz.WithInstanceID(ctx, instanceID), requestedDomain), authz.CtxData{OrgID: instanceID, ResourceOwner: instanceID})
orgID, err := id.SonyFlakeGenerator.Next() orgID, err := id.SonyFlakeGenerator.Next()
if err != nil { if err != nil {
@ -185,8 +184,6 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup, exte
} }
ctx = authz.WithConsole(ctx, setup.zitadel.projectID, setup.zitadel.consoleAppID) ctx = authz.WithConsole(ctx, setup.zitadel.projectID, setup.zitadel.consoleAppID)
setup.Org.Human.PasswordChangeRequired = true
instanceAgg := instance.NewAggregate(instanceID) instanceAgg := instance.NewAggregate(instanceID)
orgAgg := org.NewAggregate(orgID) orgAgg := org.NewAggregate(orgID)
userAgg := user.NewAggregate(userID, orgID) userAgg := user.NewAggregate(userID, orgID)
@ -302,7 +299,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup, exte
ApplicationType: domain.OIDCApplicationTypeUserAgent, ApplicationType: domain.OIDCApplicationTypeUserAgent,
AuthMethodType: domain.OIDCAuthMethodTypeNone, AuthMethodType: domain.OIDCAuthMethodTypeNone,
PostLogoutRedirectUris: []string{}, PostLogoutRedirectUris: []string{},
DevMode: !externalSecure, DevMode: !c.externalSecure,
AccessTokenType: domain.OIDCTokenTypeBearer, AccessTokenType: domain.OIDCTokenTypeBearer,
AccessTokenRoleAssertion: false, AccessTokenRoleAssertion: false,
IDTokenRoleAssertion: false, IDTokenRoleAssertion: false,

View File

@ -39,8 +39,8 @@ type AddHuman struct {
DisplayName string DisplayName string
// Email is required // Email is required
Email Email Email Email
// PreferredLang is required // PreferredLanguage is required
PreferredLang language.Tag PreferredLanguage language.Tag
// Gender is required // Gender is required
Gender domain.Gender Gender domain.Gender
//Phone represents an international phone number //Phone represents an international phone number
@ -98,6 +98,9 @@ func AddHumanCommand(a *user.Aggregate, human *AddHuman, passwordAlg crypto.Hash
return nil, errors.ThrowInvalidArgument(nil, "V2-zzad3", "Errors.Invalid.Argument") return nil, errors.ThrowInvalidArgument(nil, "V2-zzad3", "Errors.Invalid.Argument")
} }
if human.PreferredLanguage == language.Und {
return nil, errors.ThrowInvalidArgument(nil, "USER-Sfd11", "Errors.Invalid.Argument")
}
if human.FirstName = strings.TrimSpace(human.FirstName); human.FirstName == "" { if human.FirstName = strings.TrimSpace(human.FirstName); human.FirstName == "" {
return nil, errors.ThrowInvalidArgument(nil, "USER-UCej2", "Errors.Invalid.Argument") return nil, errors.ThrowInvalidArgument(nil, "USER-UCej2", "Errors.Invalid.Argument")
} }
@ -130,7 +133,7 @@ func AddHumanCommand(a *user.Aggregate, human *AddHuman, passwordAlg crypto.Hash
human.LastName, human.LastName,
human.NickName, human.NickName,
human.DisplayName, human.DisplayName,
human.PreferredLang, human.PreferredLanguage,
human.Gender, human.Gender,
human.Email.Address, human.Email.Address,
domainPolicy.UserLoginMustBeDomain, domainPolicy.UserLoginMustBeDomain,
@ -144,7 +147,7 @@ func AddHumanCommand(a *user.Aggregate, human *AddHuman, passwordAlg crypto.Hash
human.LastName, human.LastName,
human.NickName, human.NickName,
human.DisplayName, human.DisplayName,
human.PreferredLang, human.PreferredLanguage,
human.Gender, human.Gender,
human.Email.Address, human.Email.Address,
domainPolicy.UserLoginMustBeDomain, domainPolicy.UserLoginMustBeDomain,

View File

@ -93,6 +93,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
Email: Email{ Email: Email{
Address: "email@test.ch", Address: "email@test.ch",
}, },
PreferredLanguage: language.English,
}, },
}, },
res: res{ res: res{
@ -130,6 +131,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
Address: "email@test.ch", Address: "email@test.ch",
Verified: true, Verified: true,
}, },
PreferredLanguage: language.English,
}, },
}, },
res: res{ res: res{
@ -210,7 +212,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
"lastname", "lastname",
"", "",
"firstname lastname", "firstname lastname",
language.Und, language.English,
domain.GenderUnspecified, domain.GenderUnspecified,
"email@test.ch", "email@test.ch",
true, true,
@ -257,6 +259,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
Email: Email{ Email: Email{
Address: "email@test.ch", Address: "email@test.ch",
}, },
PreferredLanguage: language.English,
}, },
secretGenerator: GetMockSecretGenerator(t), secretGenerator: GetMockSecretGenerator(t),
}, },
@ -375,6 +378,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
Email: Email{ Email: Email{
Address: "email@test.ch", Address: "email@test.ch",
}, },
PreferredLanguage: language.English,
}, },
secretGenerator: GetMockSecretGenerator(t), secretGenerator: GetMockSecretGenerator(t),
}, },
@ -470,6 +474,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
Address: "email@test.ch", Address: "email@test.ch",
Verified: true, Verified: true,
}, },
PreferredLanguage: language.English,
PasswordChangeRequired: true, PasswordChangeRequired: true,
}, },
secretGenerator: GetMockSecretGenerator(t), secretGenerator: GetMockSecretGenerator(t),
@ -554,6 +559,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
Phone: Phone{ Phone: Phone{
Number: "+41711234567", Number: "+41711234567",
}, },
PreferredLanguage: language.English,
}, },
secretGenerator: GetMockSecretGenerator(t), secretGenerator: GetMockSecretGenerator(t),
}, },
@ -668,6 +674,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
Number: "+41711234567", Number: "+41711234567",
Verified: true, Verified: true,
}, },
PreferredLanguage: language.English,
}, },
secretGenerator: GetMockSecretGenerator(t), secretGenerator: GetMockSecretGenerator(t),
}, },
@ -920,8 +927,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
ChangeRequired: true, ChangeRequired: true,
}, },
Profile: &domain.Profile{ Profile: &domain.Profile{
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -940,7 +948,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
DisplayName: "firstname lastname", DisplayName: "firstname lastname",
PreferredLanguage: language.Und, PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1001,8 +1009,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
ChangeRequired: false, ChangeRequired: false,
}, },
Profile: &domain.Profile{ Profile: &domain.Profile{
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1022,7 +1031,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
DisplayName: "firstname lastname", DisplayName: "firstname lastname",
PreferredLanguage: language.Und, PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1094,8 +1103,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
human: &domain.Human{ human: &domain.Human{
Username: "username", Username: "username",
Profile: &domain.Profile{ Profile: &domain.Profile{
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1117,7 +1127,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
DisplayName: "firstname lastname", DisplayName: "firstname lastname",
PreferredLanguage: language.Und, PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1203,8 +1213,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
ChangeRequired: false, ChangeRequired: false,
}, },
Profile: &domain.Profile{ Profile: &domain.Profile{
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1226,7 +1237,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
DisplayName: "firstname lastname", DisplayName: "firstname lastname",
PreferredLanguage: language.Und, PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1312,8 +1323,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
human: &domain.Human{ human: &domain.Human{
Username: "username", Username: "username",
Profile: &domain.Profile{ Profile: &domain.Profile{
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
PreferredLanguage: language.English,
}, },
Password: &domain.Password{ Password: &domain.Password{
SecretString: "password", SecretString: "password",
@ -1339,7 +1351,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
DisplayName: "firstname lastname", DisplayName: "firstname lastname",
PreferredLanguage: language.Und, PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -1411,8 +1423,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
human: &domain.Human{ human: &domain.Human{
Username: "username", Username: "username",
Profile: &domain.Profile{ Profile: &domain.Profile{
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
PreferredLanguage: language.English,
}, },
Password: &domain.Password{ Password: &domain.Password{
SecretString: "password", SecretString: "password",
@ -1439,7 +1452,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
FirstName: "firstname", FirstName: "firstname",
LastName: "lastname", LastName: "lastname",
DisplayName: "firstname lastname", DisplayName: "firstname lastname",
PreferredLanguage: language.Und, PreferredLanguage: language.English,
}, },
Email: &domain.Email{ Email: &domain.Email{
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
@ -2767,7 +2780,7 @@ func newAddHumanEvent(password string, changeRequired bool, phone string) *user.
"lastname", "lastname",
"", "",
"firstname lastname", "firstname lastname",
language.Und, language.English,
domain.GenderUnspecified, domain.GenderUnspecified,
"email@test.ch", "email@test.ch",
true, true,
@ -2844,7 +2857,7 @@ func TestAddHumanCommand(t *testing.T) {
}, },
}, },
{ {
name: "invalid first name", name: "invalid preferred language",
args: args{ args: args{
a: agg, a: agg,
human: &AddHuman{ human: &AddHuman{
@ -2854,6 +2867,22 @@ func TestAddHumanCommand(t *testing.T) {
}, },
}, },
}, },
want: Want{
ValidationErr: errors.ThrowInvalidArgument(nil, "USER-Sfd11", "Errors.Invalid.Argument"),
},
},
{
name: "invalid first name",
args: args{
a: agg,
human: &AddHuman{
Username: "username",
PreferredLanguage: language.English,
Email: Email{
Address: "support@zitadel.ch",
},
},
},
want: Want{ want: Want{
ValidationErr: errors.ThrowInvalidArgument(nil, "USER-UCej2", "Errors.Invalid.Argument"), ValidationErr: errors.ThrowInvalidArgument(nil, "USER-UCej2", "Errors.Invalid.Argument"),
}, },
@ -2863,9 +2892,10 @@ func TestAddHumanCommand(t *testing.T) {
args: args{ args: args{
a: agg, a: agg,
human: &AddHuman{ human: &AddHuman{
Username: "username", Username: "username",
FirstName: "hurst", PreferredLanguage: language.English,
Email: Email{Address: "support@zitadel.ch"}, FirstName: "hurst",
Email: Email{Address: "support@zitadel.ch"},
}, },
}, },
want: Want{ want: Want{
@ -2877,11 +2907,12 @@ func TestAddHumanCommand(t *testing.T) {
args: args{ args: args{
a: agg, a: agg,
human: &AddHuman{ human: &AddHuman{
Email: Email{Address: "support@zitadel.ch"}, Email: Email{Address: "support@zitadel.ch"},
FirstName: "gigi", PreferredLanguage: language.English,
LastName: "giraffe", FirstName: "gigi",
Password: "short", LastName: "giraffe",
Username: "username", Password: "short",
Username: "username",
}, },
filter: NewMultiFilter().Append( filter: NewMultiFilter().Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) { func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
@ -2919,11 +2950,12 @@ func TestAddHumanCommand(t *testing.T) {
args: args{ args: args{
a: agg, a: agg,
human: &AddHuman{ human: &AddHuman{
Email: Email{Address: "support@zitadel.ch", Verified: true}, Email: Email{Address: "support@zitadel.ch", Verified: true},
FirstName: "gigi", PreferredLanguage: language.English,
LastName: "giraffe", FirstName: "gigi",
Password: "", LastName: "giraffe",
Username: "username", Password: "",
Username: "username",
}, },
passwordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)), passwordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
filter: NewMultiFilter().Append( filter: NewMultiFilter().Append(
@ -2963,7 +2995,7 @@ func TestAddHumanCommand(t *testing.T) {
"giraffe", "giraffe",
"", "",
"gigi giraffe", "gigi giraffe",
language.Und, language.English,
0, 0,
"support@zitadel.ch", "support@zitadel.ch",
true, true,