mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 20:57:24 +00:00
feat: set default language on instance (#3594)
This commit is contained in:
parent
462fe10dab
commit
79db247801
@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/config/systemdefaults"
|
||||
@ -15,9 +17,10 @@ import (
|
||||
)
|
||||
|
||||
type DefaultInstance struct {
|
||||
InstanceName string
|
||||
CustomDomain string
|
||||
Org command.OrgSetup
|
||||
InstanceName string
|
||||
CustomDomain string
|
||||
DefaultLanguage language.Tag
|
||||
Org command.OrgSetup
|
||||
|
||||
instanceSetup command.InstanceSetup
|
||||
userEncryptionKey *crypto.KeyConfig
|
||||
@ -67,6 +70,7 @@ func (mig *DefaultInstance) Execute(ctx context.Context) error {
|
||||
|
||||
mig.instanceSetup.InstanceName = mig.InstanceName
|
||||
mig.instanceSetup.CustomDomain = mig.CustomDomain
|
||||
mig.instanceSetup.DefaultLanguage = mig.DefaultLanguage
|
||||
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 == "" {
|
||||
|
@ -1,6 +1,7 @@
|
||||
S3DefaultInstance:
|
||||
InstanceName: Localhost
|
||||
CustomDomain: localhost
|
||||
DefaultLanguage: en
|
||||
Org:
|
||||
Name: ZITADEL
|
||||
Human:
|
||||
|
@ -162,6 +162,7 @@ SystemDefaults:
|
||||
|
||||
DefaultInstance:
|
||||
InstanceName:
|
||||
DefaultLanguage: en
|
||||
Org:
|
||||
Name:
|
||||
Human:
|
||||
|
@ -233,6 +233,7 @@ failed event. You can find out if it worked on the `failure_count`
|
||||
| owner_email | AddInstanceRequest.Email | - | message.required: true<br /> |
|
||||
| owner_profile | AddInstanceRequest.Profile | - | message.required: false<br /> |
|
||||
| owner_password | AddInstanceRequest.Password | - | message.required: false<br /> |
|
||||
| default_language | string | - | string.max_len: 10<br /> |
|
||||
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/text"
|
||||
caos_errors "github.com/zitadel/zitadel/internal/errors"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
@ -20,19 +21,17 @@ func (s *Server) GetSupportedLanguages(ctx context.Context, req *admin_pb.GetSup
|
||||
}
|
||||
|
||||
func (s *Server) SetDefaultLanguage(ctx context.Context, req *admin_pb.SetDefaultLanguageRequest) (*admin_pb.SetDefaultLanguageResponse, error) {
|
||||
_, err := language.Parse(req.Language)
|
||||
lang, err := language.Parse(req.Language)
|
||||
if err != nil {
|
||||
return nil, caos_errors.ThrowInvalidArgument(err, "API-39nnf", "Errors.Language.Parse")
|
||||
}
|
||||
//TODO: Will be added by silvan
|
||||
//details, err := s.command.SetDefaultLanguage(ctx, lang)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//return &admin_pb.SetDefaultLanguageResponse{
|
||||
// Details: object.DomainToChangeDetailsPb(details),
|
||||
//}, nil
|
||||
return nil, nil
|
||||
details, err := s.command.SetDefaultLanguage(ctx, lang)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.SetDefaultLanguageResponse{
|
||||
Details: object.DomainToChangeDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetDefaultLanguage(ctx context.Context, _ *admin_pb.GetDefaultLanguageRequest) (*admin_pb.GetDefaultLanguageResponse, error) {
|
||||
|
@ -47,6 +47,9 @@ func AddInstancePbToSetupInstance(req *system_pb.AddInstanceRequest, defaultInst
|
||||
defaultInstance.Org.Human.Password = req.OwnerPassword.Password
|
||||
defaultInstance.Org.Human.PasswordChangeRequired = req.OwnerPassword.PasswordChangeRequired
|
||||
}
|
||||
if lang := language.Make(req.DefaultLanguage); lang != language.Und {
|
||||
defaultInstance.DefaultLanguage = lang
|
||||
}
|
||||
|
||||
return &defaultInstance
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/console"
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
@ -32,6 +34,7 @@ type InstanceSetup struct {
|
||||
zitadel ZitadelConfig
|
||||
InstanceName string
|
||||
CustomDomain string
|
||||
DefaultLanguage language.Tag
|
||||
Org OrgSetup
|
||||
SecretGenerators struct {
|
||||
PasswordSaltCost uint
|
||||
@ -166,7 +169,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
projectAgg := project.NewAggregate(setup.zitadel.projectID, orgID)
|
||||
|
||||
validations := []preparation.Validation{
|
||||
addInstance(instanceAgg, setup.InstanceName),
|
||||
addInstance(instanceAgg, setup.InstanceName, setup.DefaultLanguage),
|
||||
addSecretGeneratorConfig(instanceAgg, domain.SecretGeneratorTypeAppSecret, setup.SecretGenerators.ClientSecret),
|
||||
addSecretGeneratorConfig(instanceAgg, domain.SecretGeneratorTypeInitCode, setup.SecretGenerators.InitializeUserCode),
|
||||
addSecretGeneratorConfig(instanceAgg, domain.SecretGeneratorTypeVerifyEmailCode, setup.SecretGenerators.EmailVerificationCode),
|
||||
@ -332,11 +335,30 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
}, nil
|
||||
}
|
||||
|
||||
func addInstance(a *instance.Aggregate, instanceName string) preparation.Validation {
|
||||
func (c *Commands) SetDefaultLanguage(ctx context.Context, defaultLanguage language.Tag) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
validation := c.prepareSetDefaultLanguage(instanceAgg, defaultLanguage)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: events[len(events)-1].Sequence(),
|
||||
EventDate: events[len(events)-1].CreationDate(),
|
||||
ResourceOwner: events[len(events)-1].Aggregate().InstanceID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func addInstance(a *instance.Aggregate, instanceName string, defaultLanguage language.Tag) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
return []eventstore.Command{
|
||||
instance.NewInstanceAddedEvent(ctx, &a.Aggregate, instanceName),
|
||||
instance.NewDefaultLanguageSetEvent(ctx, &a.Aggregate, defaultLanguage),
|
||||
}, nil
|
||||
}, nil
|
||||
}
|
||||
@ -385,3 +407,35 @@ func (c *Commands) setIAMProject(ctx context.Context, iamAgg *eventstore.Aggrega
|
||||
}
|
||||
return instance.NewIAMProjectSetEvent(ctx, iamAgg, projectID), nil
|
||||
}
|
||||
|
||||
func (c *Commands) prepareSetDefaultLanguage(a *instance.Aggregate, defaultLanguage language.Tag) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if defaultLanguage == language.Und {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "INST-28nlD", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel, err := getInstanceWriteModel(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if writeModel.DefaultLanguage == defaultLanguage {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "INST-DS3rq", "Errors.Instance.NotChanged")
|
||||
}
|
||||
return []eventstore.Command{instance.NewDefaultLanguageSetEvent(ctx, &a.Aggregate, defaultLanguage)}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func getInstanceWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer) (*InstanceWriteModel, error) {
|
||||
writeModel := NewInstanceWriteModel(authz.GetInstance(ctx).InstanceID())
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(events) == 0 {
|
||||
return writeModel, nil
|
||||
}
|
||||
writeModel.AppendEvents(events...)
|
||||
err = writeModel.Reduce()
|
||||
return writeModel, err
|
||||
}
|
||||
|
@ -98,9 +98,6 @@ func AddHumanCommand(a *user.Aggregate, human *AddHuman, passwordAlg crypto.Hash
|
||||
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 == "" {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "USER-UCej2", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
@ -2856,21 +2856,6 @@ func TestAddHumanCommand(t *testing.T) {
|
||||
ValidationErr: errors.ThrowInvalidArgument(nil, "USER-Ec7dM", "Errors.Invalid.Argument"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid preferred language",
|
||||
args: args{
|
||||
a: agg,
|
||||
human: &AddHuman{
|
||||
Username: "username",
|
||||
Email: Email{
|
||||
Address: "support@zitadel.ch",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: Want{
|
||||
ValidationErr: errors.ThrowInvalidArgument(nil, "USER-Sfd11", "Errors.Invalid.Argument"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid first name",
|
||||
args: args{
|
||||
|
@ -281,6 +281,7 @@ func prepareInstancesQuery() (sq.SelectBuilder, func(*sql.Rows) (*Instances, err
|
||||
&lang,
|
||||
&count,
|
||||
)
|
||||
instance.DefaultLang = language.Make(lang)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -378,6 +379,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows)
|
||||
InstanceID: instance.ID,
|
||||
})
|
||||
}
|
||||
instance.DefaultLang = language.Make(lang)
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-Dfbe2", "Errors.Query.CloseRows")
|
||||
}
|
||||
|
@ -4,15 +4,15 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultLanguageSetEventType eventstore.EventType = "iam.default.language.set"
|
||||
DefaultLanguageSetEventType eventstore.EventType = "instance.default.language.set"
|
||||
)
|
||||
|
||||
type DefaultLanguageSetEvent struct {
|
||||
|
@ -342,6 +342,7 @@ message AddInstanceRequest {
|
||||
Email owner_email = 5 [(validate.rules).message.required = true];
|
||||
Profile owner_profile = 6 [(validate.rules).message.required = false];
|
||||
Password owner_password = 7 [(validate.rules).message.required = false];
|
||||
string default_language = 8 [(validate.rules).string = {max_len: 10}];
|
||||
}
|
||||
|
||||
message AddInstanceResponse {
|
||||
|
Loading…
x
Reference in New Issue
Block a user