mirror of
https://github.com/zitadel/zitadel
synced 2024-11-22 18:44:40 +00:00
fix: import user, hide login name suffix (#1474)
* fix: import user, and label policy command side * feat: Import user and hide loginname suffix (#1464) * fix: import user * fix: label policy * fix: label policy * fix: label policy * fix: migrations * fix: migrations * fix: migrations * fix: label policy * loginSuffix in login ui * suffix * fix cursor on disabled user selection Co-authored-by: Livio Amstutz <livio.a@gmail.com> (cherry picked from commit03ddb8fc38
) * feat: Import user and hide loginname suffix (#1464) * fix: import user * fix: label policy * fix: label policy * fix: label policy * fix: migrations * fix: migrations * fix: migrations * fix: label policy * loginSuffix in login ui * suffix * fix cursor on disabled user selection Co-authored-by: Livio Amstutz <livio.a@gmail.com> (cherry picked from commit03ddb8fc38
) * feat: Import user and hide loginname suffix (#1464) * fix: import user * fix: label policy * fix: label policy * fix: label policy * fix: migrations * fix: migrations * fix: migrations * fix: label policy * loginSuffix in login ui * suffix * fix cursor on disabled user selection Co-authored-by: Livio Amstutz <livio.a@gmail.com> (cherry picked from commit03ddb8fc38
) * fix: label policy events * loginname placeholder * fix: tests * fix: tests * Update internal/command/iam_policy_label_model.go Co-authored-by: Livio Amstutz <livio.a@gmail.com> Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
parent
d7255130a4
commit
4d10f3e715
@ -7,7 +7,8 @@ import (
|
||||
|
||||
func updateLabelPolicyToDomain(policy *admin_pb.UpdateLabelPolicyRequest) *domain.LabelPolicy {
|
||||
return &domain.LabelPolicy{
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||
}
|
||||
}
|
||||
|
64
internal/api/grpc/management/policy_label.go
Normal file
64
internal/api/grpc/management/policy_label.go
Normal file
@ -0,0 +1,64 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
policy_grpc "github.com/caos/zitadel/internal/api/grpc/policy"
|
||||
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
func (s *Server) GetLabelPolicy(ctx context.Context, req *mgmt_pb.GetLabelPolicyRequest) (*mgmt_pb.GetLabelPolicyResponse, error) {
|
||||
policy, err := s.org.GetLabelPolicy(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.GetLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetDefaultLabelPolicy(ctx context.Context, req *mgmt_pb.GetDefaultLabelPolicyRequest) (*mgmt_pb.GetDefaultLabelPolicyResponse, error) {
|
||||
policy, err := s.org.GetDefaultLabelPolicy(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.GetDefaultLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddCustomLabelPolicy(ctx context.Context, req *mgmt_pb.AddCustomLabelPolicyRequest) (*mgmt_pb.AddCustomLabelPolicyResponse, error) {
|
||||
policy, err := s.command.AddLabelPolicy(ctx, authz.GetCtxData(ctx).OrgID, addLabelPolicyToDomain(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.AddCustomLabelPolicyResponse{
|
||||
Details: object.AddToDetailsPb(
|
||||
policy.Sequence,
|
||||
policy.ChangeDate,
|
||||
policy.ResourceOwner,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateCustomLabelPolicy(ctx context.Context, req *mgmt_pb.UpdateCustomLabelPolicyRequest) (*mgmt_pb.UpdateCustomLabelPolicyResponse, error) {
|
||||
policy, err := s.command.ChangeLabelPolicy(ctx, authz.GetCtxData(ctx).OrgID, updateLabelPolicyToDomain(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.UpdateCustomLabelPolicyResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
policy.Sequence,
|
||||
policy.ChangeDate,
|
||||
policy.ResourceOwner,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ResetLabelPolicyToDefault(ctx context.Context, req *mgmt_pb.ResetLabelPolicyToDefaultRequest) (*mgmt_pb.ResetLabelPolicyToDefaultResponse, error) {
|
||||
objectDetails, err := s.command.RemoveLabelPolicy(ctx, authz.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.ResetLabelPolicyToDefaultResponse{
|
||||
Details: object.DomainToChangeDetailsPb(objectDetails),
|
||||
}, nil
|
||||
}
|
22
internal/api/grpc/management/policy_label_converter.go
Normal file
22
internal/api/grpc/management/policy_label_converter.go
Normal file
@ -0,0 +1,22 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
func addLabelPolicyToDomain(p *mgmt_pb.AddCustomLabelPolicyRequest) *domain.LabelPolicy {
|
||||
return &domain.LabelPolicy{
|
||||
PrimaryColor: p.PrimaryColor,
|
||||
SecondaryColor: p.SecondaryColor,
|
||||
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
||||
}
|
||||
}
|
||||
|
||||
func updateLabelPolicyToDomain(p *mgmt_pb.UpdateCustomLabelPolicyRequest) *domain.LabelPolicy {
|
||||
return &domain.LabelPolicy{
|
||||
PrimaryColor: p.PrimaryColor,
|
||||
SecondaryColor: p.SecondaryColor,
|
||||
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
||||
}
|
||||
}
|
@ -87,6 +87,21 @@ func (s *Server) AddHumanUser(ctx context.Context, req *mgmt_pb.AddHumanUserRequ
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ImportHumanUser(ctx context.Context, req *mgmt_pb.ImportHumanUserRequest) (*mgmt_pb.ImportHumanUserResponse, error) {
|
||||
human, err := s.command.ImportHuman(ctx, authz.GetCtxData(ctx).OrgID, ImportHumanUserRequestToDomain(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.ImportHumanUserResponse{
|
||||
UserId: human.AggregateID,
|
||||
Details: obj_grpc.AddToDetailsPb(
|
||||
human.Sequence,
|
||||
human.ChangeDate,
|
||||
human.ResourceOwner,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddMachineUser(ctx context.Context, req *mgmt_pb.AddMachineUserRequest) (*mgmt_pb.AddMachineUserResponse, error) {
|
||||
machine, err := s.command.AddMachine(ctx, authz.GetCtxData(ctx).OrgID, AddMachineUserRequestToDomain(req))
|
||||
if err != nil {
|
||||
|
@ -69,6 +69,38 @@ func AddHumanUserRequestToDomain(req *mgmt_pb.AddHumanUserRequest) *domain.Human
|
||||
return h
|
||||
}
|
||||
|
||||
func ImportHumanUserRequestToDomain(req *mgmt_pb.ImportHumanUserRequest) *domain.Human {
|
||||
h := &domain.Human{
|
||||
Username: req.UserName,
|
||||
}
|
||||
preferredLanguage, err := language.Parse(req.Profile.PreferredLanguage)
|
||||
logging.Log("MANAG-3GUFJ").OnError(err).Debug("language malformed")
|
||||
h.Profile = &domain.Profile{
|
||||
FirstName: req.Profile.FirstName,
|
||||
LastName: req.Profile.LastName,
|
||||
NickName: req.Profile.NickName,
|
||||
DisplayName: req.Profile.DisplayName,
|
||||
PreferredLanguage: preferredLanguage,
|
||||
Gender: user_grpc.GenderToDomain(req.Profile.Gender),
|
||||
}
|
||||
h.Email = &domain.Email{
|
||||
EmailAddress: req.Email.Email,
|
||||
IsEmailVerified: req.Email.IsEmailVerified,
|
||||
}
|
||||
if req.Phone != nil {
|
||||
h.Phone = &domain.Phone{
|
||||
PhoneNumber: req.Phone.Phone,
|
||||
IsPhoneVerified: req.Phone.IsPhoneVerified,
|
||||
}
|
||||
}
|
||||
if req.Password != "" {
|
||||
h.Password = &domain.Password{SecretString: req.Password}
|
||||
h.Password.ChangeRequired = true
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func AddMachineUserRequestToDomain(req *mgmt_pb.AddMachineUserRequest) *domain.Machine {
|
||||
return &domain.Machine{
|
||||
Username: req.UserName,
|
||||
|
@ -8,9 +8,10 @@ import (
|
||||
|
||||
func ModelLabelPolicyToPb(policy *model.LabelPolicyView) *policy_pb.LabelPolicy {
|
||||
return &policy_pb.LabelPolicy{
|
||||
IsDefault: policy.Default,
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
IsDefault: policy.Default,
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||
Details: object.ToViewDetailsPb(
|
||||
policy.Sequence,
|
||||
policy.CreationDate,
|
||||
|
@ -244,7 +244,7 @@ func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAge
|
||||
if request.RequestedOrgID != "" && request.RequestedOrgID != user.ResourceOwner {
|
||||
return errors.ThrowPreconditionFailed(nil, "EVENT-fJe2a", "Errors.User.NotAllowedOrg")
|
||||
}
|
||||
request.SetUserInfo(user.ID, user.PreferredLoginName, user.DisplayName, user.ResourceOwner)
|
||||
request.SetUserInfo(user.ID, user.UserName, user.PreferredLoginName, user.DisplayName, user.ResourceOwner)
|
||||
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
|
||||
}
|
||||
|
||||
@ -425,21 +425,30 @@ func (repo *AuthRequestRepo) fillLoginPolicy(ctx context.Context, request *domai
|
||||
orgID = repo.IAMID
|
||||
}
|
||||
|
||||
policy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, orgID)
|
||||
loginPolicy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.LoginPolicy = policy
|
||||
request.LoginPolicy = loginPolicy
|
||||
if idpProviders != nil {
|
||||
request.AllowedExternalIDPs = idpProviders
|
||||
}
|
||||
labelPolicy, err := repo.getLabelPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.LabelPolicy = labelPolicy
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain.AuthRequest, loginName string) (err error) {
|
||||
user := new(user_view_model.UserView)
|
||||
if request.RequestedOrgID != "" {
|
||||
user, err = repo.View.UserByLoginNameAndResourceOwner(loginName, request.RequestedOrgID)
|
||||
preferredLoginName := loginName
|
||||
if request.RequestedOrgID != "" {
|
||||
preferredLoginName += "@" + request.RequestedPrimaryDomain
|
||||
}
|
||||
user, err = repo.View.UserByLoginNameAndResourceOwner(preferredLoginName, request.RequestedOrgID)
|
||||
} else {
|
||||
user, err = repo.View.UserByLoginName(loginName)
|
||||
if err == nil {
|
||||
@ -453,7 +462,7 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
||||
return err
|
||||
}
|
||||
|
||||
request.SetUserInfo(user.ID, loginName, "", user.ResourceOwner)
|
||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", user.ResourceOwner)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -496,7 +505,7 @@ func (repo *AuthRequestRepo) checkExternalUserLogin(request *domain.AuthRequest,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.SetUserInfo(externalIDP.UserID, "", "", externalIDP.ResourceOwner)
|
||||
request.SetUserInfo(externalIDP.UserID, "", "", "", externalIDP.ResourceOwner)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -599,6 +608,7 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *domain.AuthRequest)
|
||||
users[i] = domain.UserSelection{
|
||||
UserID: session.UserID,
|
||||
DisplayName: session.DisplayName,
|
||||
UserName: session.UserName,
|
||||
LoginName: session.LoginName,
|
||||
UserSessionState: auth_req_model.UserSessionStateToDomain(session.State),
|
||||
SelectionPossible: request.RequestedOrgID == "" || request.RequestedOrgID == session.ResourceOwner,
|
||||
@ -695,6 +705,21 @@ func (repo *AuthRequestRepo) getLoginPolicy(ctx context.Context, orgID string) (
|
||||
return iam_es_model.LoginPolicyViewToModel(policy), err
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) getLabelPolicy(ctx context.Context, orgID string) (*domain.LabelPolicy, error) {
|
||||
policy, err := repo.View.LabelPolicyByAggregateID(orgID)
|
||||
if errors.IsNotFound(err) {
|
||||
policy, err = repo.View.LabelPolicyByAggregateID(repo.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy.Default = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return policy.ToDomain(), err
|
||||
}
|
||||
|
||||
func setOrgID(orgViewProvider orgViewProvider, request *domain.AuthRequest) error {
|
||||
primaryDomain := request.GetScopeOrgPrimaryDomain()
|
||||
if primaryDomain == "" {
|
||||
@ -707,6 +732,7 @@ func setOrgID(orgViewProvider orgViewProvider, request *domain.AuthRequest) erro
|
||||
}
|
||||
request.RequestedOrgID = org.ID
|
||||
request.RequestedOrgName = org.Name
|
||||
request.RequestedPrimaryDomain = primaryDomain
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
||||
newOrgIAMPolicy(
|
||||
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
|
||||
newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount, es}),
|
||||
newLabelPolicy(handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount, es}),
|
||||
}
|
||||
}
|
||||
|
||||
|
104
internal/auth/repository/eventsourcing/handler/label_policy.go
Normal file
104
internal/auth/repository/eventsourcing/handler/label_policy.go
Normal file
@ -0,0 +1,104 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
v1 "github.com/caos/zitadel/internal/eventstore/v1"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
const (
|
||||
labelPolicyTable = "auth.label_policies"
|
||||
)
|
||||
|
||||
type LabelPolicy struct {
|
||||
handler
|
||||
subscription *v1.Subscription
|
||||
}
|
||||
|
||||
func newLabelPolicy(handler handler) *LabelPolicy {
|
||||
h := &LabelPolicy{
|
||||
handler: handler,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) subscribe() {
|
||||
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||
go func() {
|
||||
for event := range m.subscription.Events {
|
||||
query.ReduceEvent(m, event)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) ViewModel() string {
|
||||
return labelPolicyTable
|
||||
}
|
||||
|
||||
func (_ *LabelPolicy) AggregateTypes() []models.AggregateType {
|
||||
return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) CurrentSequence() (uint64, error) {
|
||||
sequence, err := m.view.GetLatestLabelPolicySequence()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return sequence.CurrentSequence, nil
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
|
||||
sequence, err := m.view.GetLatestLabelPolicySequence()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(m.AggregateTypes()...).
|
||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) Reduce(event *models.Event) (err error) {
|
||||
switch event.AggregateType {
|
||||
case model.OrgAggregate, iam_es_model.IAMAggregate:
|
||||
err = m.processLabelPolicy(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) {
|
||||
policy := new(iam_model.LabelPolicyView)
|
||||
switch event.Type {
|
||||
case iam_es_model.LabelPolicyAdded, model.LabelPolicyAdded:
|
||||
err = policy.AppendEvent(event)
|
||||
case iam_es_model.LabelPolicyChanged, model.LabelPolicyChanged:
|
||||
policy, err = m.view.LabelPolicyByAggregateID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = policy.AppendEvent(event)
|
||||
default:
|
||||
return m.view.ProcessedLabelPolicySequence(event)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutLabelPolicy(policy, event)
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in label policy handler")
|
||||
return spooler.HandleError(event, err, m.view.GetLatestLabelPolicyFailedEvent, m.view.ProcessedLabelPolicyFailedEvent, m.view.ProcessedLabelPolicySequence, m.errorCountUntilSkip)
|
||||
}
|
||||
|
||||
func (m *LabelPolicy) OnSuccess() error {
|
||||
return spooler.HandleSuccess(m.view.UpdateLabelPolicySpoolerRunTimestamp)
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
labelPolicyTable = "auth.label_policies"
|
||||
)
|
||||
|
||||
func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyView, error) {
|
||||
return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID)
|
||||
}
|
||||
|
||||
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
|
||||
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedLabelPolicySequence(event)
|
||||
}
|
||||
|
||||
func (v *View) DeleteLabelPolicy(aggregateID string, event *models.Event) error {
|
||||
err := view.DeleteLabelPolicy(v.Db, labelPolicyTable, aggregateID)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedLabelPolicySequence(event)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) {
|
||||
return v.latestSequence(labelPolicyTable)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedLabelPolicySequence(event *models.Event) error {
|
||||
return v.saveCurrentSequence(labelPolicyTable, event)
|
||||
}
|
||||
|
||||
func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error {
|
||||
return v.updateSpoolerRunSequence(labelPolicyTable)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||
return v.latestFailedEvent(labelPolicyTable, sequence)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedLabelPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||
return v.saveFailedEvent(failedEvent)
|
||||
}
|
@ -27,23 +27,26 @@ type AuthRequest struct {
|
||||
MaxAuthAge uint32
|
||||
Request Request
|
||||
|
||||
levelOfAssurance LevelOfAssurance
|
||||
UserID string
|
||||
LoginName string
|
||||
DisplayName string
|
||||
UserOrgID string
|
||||
RequestedOrgID string
|
||||
RequestedOrgName string
|
||||
SelectedIDPConfigID string
|
||||
LinkingUsers []*ExternalUser
|
||||
PossibleSteps []NextStep
|
||||
PasswordVerified bool
|
||||
MFAsVerified []MFAType
|
||||
Audience []string
|
||||
AuthTime time.Time
|
||||
Code string
|
||||
LoginPolicy *model.LoginPolicyView
|
||||
AllowedExternalIDPs []*model.IDPProviderView
|
||||
levelOfAssurance LevelOfAssurance
|
||||
UserID string
|
||||
UserName string
|
||||
LoginName string
|
||||
DisplayName string
|
||||
UserOrgID string
|
||||
RequestedOrgID string
|
||||
RequestedOrgName string
|
||||
RequestedPrimaryDomain string
|
||||
SelectedIDPConfigID string
|
||||
LinkingUsers []*ExternalUser
|
||||
PossibleSteps []NextStep
|
||||
PasswordVerified bool
|
||||
MFAsVerified []MFAType
|
||||
Audience []string
|
||||
AuthTime time.Time
|
||||
Code string
|
||||
LoginPolicy *model.LoginPolicyView
|
||||
LabelPolicy *model.LabelPolicyView
|
||||
AllowedExternalIDPs []*model.IDPProviderView
|
||||
}
|
||||
|
||||
type ExternalUser struct {
|
||||
@ -123,8 +126,9 @@ func (a *AuthRequest) WithCurrentInfo(info *BrowserInfo) *AuthRequest {
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *AuthRequest) SetUserInfo(userID, loginName, displayName, userOrgID string) {
|
||||
func (a *AuthRequest) SetUserInfo(userID, userName, loginName, displayName, userOrgID string) {
|
||||
a.UserID = userID
|
||||
a.UserName = userName
|
||||
a.LoginName = loginName
|
||||
a.DisplayName = displayName
|
||||
a.UserOrgID = userOrgID
|
||||
|
@ -54,6 +54,7 @@ func (s *SelectUserStep) Type() NextStepType {
|
||||
type UserSelection struct {
|
||||
UserID string
|
||||
DisplayName string
|
||||
UserName string
|
||||
LoginName string
|
||||
UserSessionState UserSessionState
|
||||
SelectionPossible bool
|
||||
|
@ -46,9 +46,10 @@ func writeModelToLoginPolicy(wm *LoginPolicyWriteModel) *domain.LoginPolicy {
|
||||
|
||||
func writeModelToLabelPolicy(wm *LabelPolicyWriteModel) *domain.LabelPolicy {
|
||||
return &domain.LabelPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
PrimaryColor: wm.PrimaryColor,
|
||||
SecondaryColor: wm.SecondaryColor,
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
PrimaryColor: wm.PrimaryColor,
|
||||
SecondaryColor: wm.SecondaryColor,
|
||||
HideLoginNameSuffix: wm.HideLoginNameSuffix,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ func (c *Commands) addDefaultLabelPolicy(ctx context.Context, iamAgg *eventstore
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewLabelPolicyAddedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor), nil
|
||||
return iam_repo.NewLabelPolicyAddedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor, policy.HideLoginNameSuffix), nil
|
||||
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ func (c *Commands) ChangeDefaultLabelPolicy(ctx context.Context, policy *domain.
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor, policy.HideLoginNameSuffix)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ func (wm *IAMLabelPolicyWriteModel) NewChangedEvent(
|
||||
aggregate *eventstore.Aggregate,
|
||||
primaryColor,
|
||||
secondaryColor string,
|
||||
hideLoginNameSuffix bool,
|
||||
) (*iam.LabelPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.LabelPolicyChanges, 0)
|
||||
if wm.PrimaryColor != primaryColor {
|
||||
@ -61,6 +62,9 @@ func (wm *IAMLabelPolicyWriteModel) NewChangedEvent(
|
||||
if wm.SecondaryColor != secondaryColor {
|
||||
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
||||
}
|
||||
if wm.HideLoginNameSuffix != hideLoginNameSuffix {
|
||||
changes = append(changes, policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -68,8 +69,9 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -89,6 +91,7 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
},
|
||||
@ -98,8 +101,9 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -108,8 +112,9 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
||||
AggregateID: "IAM",
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -199,6 +204,7 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -207,8 +213,9 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -226,13 +233,14 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newDefaultLabelPolicyChangedEvent(context.Background(), "primary-color-change", "secondary-color-change"),
|
||||
newDefaultLabelPolicyChangedEvent(context.Background(), "primary-color-change", "secondary-color-change", false),
|
||||
),
|
||||
},
|
||||
),
|
||||
@ -241,8 +249,9 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
HideLoginNameSuffix: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -251,8 +260,9 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
||||
AggregateID: "IAM",
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
HideLoginNameSuffix: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -276,12 +286,13 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newDefaultLabelPolicyChangedEvent(ctx context.Context, primaryColor, secondaryColor string) *iam.LabelPolicyChangedEvent {
|
||||
func newDefaultLabelPolicyChangedEvent(ctx context.Context, primaryColor, secondaryColor string, hideLoginNameSuffix bool) *iam.LabelPolicyChangedEvent {
|
||||
event, _ := iam.NewLabelPolicyChangedEvent(ctx,
|
||||
&iam.NewAggregate().Aggregate,
|
||||
[]policy.LabelPolicyChanges{
|
||||
policy.ChangePrimaryColor(primaryColor),
|
||||
policy.ChangeSecondaryColor(secondaryColor),
|
||||
policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix),
|
||||
},
|
||||
)
|
||||
return event
|
||||
|
@ -25,7 +25,7 @@ func (c *Commands) AddLabelPolicy(ctx context.Context, resourceOwner string, pol
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, org.NewLabelPolicyAddedEvent(ctx, orgAgg, policy.PrimaryColor, policy.SecondaryColor))
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, org.NewLabelPolicyAddedEvent(ctx, orgAgg, policy.PrimaryColor, policy.SecondaryColor, policy.HideLoginNameSuffix))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -53,7 +53,7 @@ func (c *Commands) ChangeLabelPolicy(ctx context.Context, resourceOwner string,
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.PrimaryColor, policy.SecondaryColor)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.PrimaryColor, policy.SecondaryColor, policy.HideLoginNameSuffix)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
|
||||
}
|
||||
@ -69,19 +69,26 @@ func (c *Commands) ChangeLabelPolicy(ctx context.Context, resourceOwner string,
|
||||
return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveLabelPolicy(ctx context.Context, orgID string) error {
|
||||
func (c *Commands) RemoveLabelPolicy(ctx context.Context, orgID string) (*domain.ObjectDetails, error) {
|
||||
if orgID == "" {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "Org-Mf9sf", "Errors.ResourceOwnerMissing")
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-Mf9sf", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
existingPolicy := NewOrgLabelPolicyWriteModel(orgID)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-3M9df", "Errors.Org.LabelPolicy.NotFound")
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-3M9df", "Errors.Org.LabelPolicy.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
_, err = c.eventstore.PushEvents(ctx, org.NewLabelPolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, org.NewLabelPolicyRemovedEvent(ctx, orgAgg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&existingPolicy.LabelPolicyWriteModel.WriteModel), nil
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ func (wm *OrgLabelPolicyWriteModel) NewChangedEvent(
|
||||
aggregate *eventstore.Aggregate,
|
||||
primaryColor,
|
||||
secondaryColor string,
|
||||
hideLoginNameSuffix bool,
|
||||
) (*org.LabelPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.LabelPolicyChanges, 0)
|
||||
if wm.PrimaryColor != primaryColor {
|
||||
@ -60,6 +61,9 @@ func (wm *OrgLabelPolicyWriteModel) NewChangedEvent(
|
||||
if wm.SecondaryColor != secondaryColor {
|
||||
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
||||
}
|
||||
if wm.HideLoginNameSuffix != hideLoginNameSuffix {
|
||||
changes = append(changes, policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -91,8 +92,9 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -112,6 +114,7 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
},
|
||||
@ -122,8 +125,9 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -132,8 +136,9 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -244,6 +249,7 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -253,8 +259,9 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
PrimaryColor: "primary-color",
|
||||
SecondaryColor: "secondary-color",
|
||||
HideLoginNameSuffix: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -272,13 +279,14 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newLabelPolicyChangedEvent(context.Background(), "org1", "primary-color-change", "secondary-color-change"),
|
||||
newLabelPolicyChangedEvent(context.Background(), "org1", "primary-color-change", "secondary-color-change", false),
|
||||
),
|
||||
},
|
||||
),
|
||||
@ -288,8 +296,9 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
HideLoginNameSuffix: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -298,8 +307,9 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
PrimaryColor: "primary-color-change",
|
||||
SecondaryColor: "secondary-color-change",
|
||||
HideLoginNameSuffix: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -381,6 +391,7 @@ func TestCommandSide_RemoveLabelPolicy(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"primary-color",
|
||||
"secondary-color",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -406,7 +417,7 @@ func TestCommandSide_RemoveLabelPolicy(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
err := r.RemoveLabelPolicy(tt.args.ctx, tt.args.orgID)
|
||||
_, err := r.RemoveLabelPolicy(tt.args.ctx, tt.args.orgID)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -417,12 +428,13 @@ func TestCommandSide_RemoveLabelPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newLabelPolicyChangedEvent(ctx context.Context, orgID, primaryColor, secondaryColor string) *org.LabelPolicyChangedEvent {
|
||||
func newLabelPolicyChangedEvent(ctx context.Context, orgID, primaryColor, secondaryColor string, hideLoginNameSuffix bool) *org.LabelPolicyChangedEvent {
|
||||
event, _ := org.NewLabelPolicyChangedEvent(ctx,
|
||||
&org.NewAggregate(orgID, orgID).Aggregate,
|
||||
[]policy.LabelPolicyChanges{
|
||||
policy.ChangePrimaryColor(primaryColor),
|
||||
policy.ChangeSecondaryColor(secondaryColor),
|
||||
policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix),
|
||||
},
|
||||
)
|
||||
return event
|
||||
|
@ -9,8 +9,9 @@ import (
|
||||
type LabelPolicyWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
HideLoginNameSuffix bool
|
||||
|
||||
State domain.PolicyState
|
||||
}
|
||||
@ -21,6 +22,7 @@ func (wm *LabelPolicyWriteModel) Reduce() error {
|
||||
case *policy.LabelPolicyAddedEvent:
|
||||
wm.PrimaryColor = e.PrimaryColor
|
||||
wm.SecondaryColor = e.SecondaryColor
|
||||
wm.HideLoginNameSuffix = e.HideLoginNameSuffix
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.LabelPolicyChangedEvent:
|
||||
if e.PrimaryColor != nil {
|
||||
@ -29,6 +31,9 @@ func (wm *LabelPolicyWriteModel) Reduce() error {
|
||||
if e.SecondaryColor != nil {
|
||||
wm.SecondaryColor = *e.SecondaryColor
|
||||
}
|
||||
if e.HideLoginNameSuffix != nil {
|
||||
wm.HideLoginNameSuffix = *e.HideLoginNameSuffix
|
||||
}
|
||||
case *policy.LabelPolicyRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
|
@ -50,7 +50,46 @@ func (c *Commands) AddHuman(ctx context.Context, orgID string, human *domain.Hum
|
||||
return writeModelToHuman(addedHuman), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.Human) (*domain.Human, error) {
|
||||
if orgID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-5N8fs", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
orgIAMPolicy, err := c.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-2N9fs", "Errors.Org.OrgIAMPolicy.NotFound")
|
||||
}
|
||||
pwPolicy, err := c.getOrgPasswordComplexityPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-4N8gs", "Errors.Org.PasswordComplexity.NotFound")
|
||||
}
|
||||
events, addedHuman, err := c.importHuman(ctx, orgID, human, orgIAMPolicy, pwPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = AppendAndReduce(addedHuman, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToHuman(addedHuman), nil
|
||||
}
|
||||
|
||||
func (c *Commands) addHuman(ctx context.Context, orgID string, human *domain.Human, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy) ([]eventstore.EventPusher, *HumanWriteModel, error) {
|
||||
if orgID == "" || !human.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
|
||||
}
|
||||
if human.Password != nil && human.SecretString != "" {
|
||||
human.ChangeRequired = true
|
||||
}
|
||||
return c.createHuman(ctx, orgID, human, nil, false, orgIAMPolicy, pwPolicy)
|
||||
}
|
||||
|
||||
func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.Human, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy) ([]eventstore.EventPusher, *HumanWriteModel, error) {
|
||||
if orgID == "" || !human.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
|
||||
}
|
||||
@ -104,6 +143,9 @@ func (c *Commands) registerHuman(ctx context.Context, orgID string, human *domai
|
||||
if err != nil {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.Org.PasswordComplexity.NotFound")
|
||||
}
|
||||
if human.Password != nil && human.SecretString != "" {
|
||||
human.ChangeRequired = false
|
||||
}
|
||||
return c.createHuman(ctx, orgID, human, externalIDP, true, orgIAMPolicy, pwPolicy)
|
||||
}
|
||||
|
||||
@ -117,9 +159,12 @@ func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.
|
||||
}
|
||||
human.AggregateID = userID
|
||||
human.SetNamesAsDisplayname()
|
||||
if err := human.HashPasswordIfExisting(pwPolicy, c.userPasswordAlg, !selfregister); err != nil {
|
||||
return nil, nil, err
|
||||
if human.Password != nil {
|
||||
if err := human.HashPasswordIfExisting(pwPolicy, c.userPasswordAlg, human.ChangeRequired); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
addedHuman := NewHumanWriteModel(human.AggregateID, orgID)
|
||||
//TODO: adlerhurst maybe we could simplify the code below
|
||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||
|
@ -171,51 +171,6 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org policy check failed, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "email@test.ch",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with initial code), ok",
|
||||
fields: fields{
|
||||
@ -695,6 +650,553 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretGenerator crypto.Generator
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
orgID string
|
||||
human *domain.Human
|
||||
}
|
||||
type res struct {
|
||||
want *domain.Human
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "orgid missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org policy not found, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "password policy not found, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(),
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "user invalid, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with password and initial code), ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("password", true, ""),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanInitialCodeAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("a"),
|
||||
},
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Password: &domain.Password{
|
||||
SecretString: "password",
|
||||
ChangeRequired: true,
|
||||
},
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.Und,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
State: domain.UserStateInitial,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human email verified password change not required, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("password", false, ""),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanEmailVerifiedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Password: &domain.Password{
|
||||
SecretString: "password",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.Und,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
State: domain.UserStateActive,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with phone), ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("password", false, "+41711234567"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanInitialCodeAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("a"),
|
||||
},
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanPhoneCodeAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("a"),
|
||||
},
|
||||
time.Hour*1)),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Password: &domain.Password{
|
||||
SecretString: "password",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
Phone: &domain.Phone{
|
||||
PhoneNumber: "+41711234567",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.Und,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
Phone: &domain.Phone{
|
||||
PhoneNumber: "+41711234567",
|
||||
},
|
||||
State: domain.UserStateInitial,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with verified phone), ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("password", false, "+41711234567"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanInitialCodeAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("a"),
|
||||
},
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanPhoneVerifiedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Password: &domain.Password{
|
||||
SecretString: "password",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
Phone: &domain.Phone{
|
||||
PhoneNumber: "+41711234567",
|
||||
IsPhoneVerified: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.Und,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
Phone: &domain.Phone{
|
||||
PhoneNumber: "+41711234567",
|
||||
},
|
||||
State: domain.UserStateInitial,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
initializeUserCode: tt.fields.secretGenerator,
|
||||
phoneVerificationCode: tt.fields.secretGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
}
|
||||
got, err := r.ImportHuman(tt.args.ctx, tt.args.orgID, tt.args.human)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
@ -836,54 +1338,6 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org policy check failed, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOrgIAMPolicyAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "email@test.ch",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
Password: &domain.Password{
|
||||
SecretString: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with password and initial code), ok",
|
||||
fields: fields{
|
||||
|
@ -1,10 +1,12 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"golang.org/x/text/language"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
type AuthRequest struct {
|
||||
@ -23,23 +25,26 @@ type AuthRequest struct {
|
||||
MaxAuthAge uint32
|
||||
Request Request
|
||||
|
||||
levelOfAssurance LevelOfAssurance
|
||||
UserID string
|
||||
LoginName string
|
||||
DisplayName string
|
||||
UserOrgID string
|
||||
RequestedOrgID string
|
||||
RequestedOrgName string
|
||||
SelectedIDPConfigID string
|
||||
LinkingUsers []*ExternalUser
|
||||
PossibleSteps []NextStep
|
||||
PasswordVerified bool
|
||||
MFAsVerified []MFAType
|
||||
Audience []string
|
||||
AuthTime time.Time
|
||||
Code string
|
||||
LoginPolicy *LoginPolicy
|
||||
AllowedExternalIDPs []*IDPProvider
|
||||
levelOfAssurance LevelOfAssurance
|
||||
UserID string
|
||||
UserName string
|
||||
LoginName string
|
||||
DisplayName string
|
||||
UserOrgID string
|
||||
RequestedOrgID string
|
||||
RequestedOrgName string
|
||||
RequestedPrimaryDomain string
|
||||
SelectedIDPConfigID string
|
||||
LinkingUsers []*ExternalUser
|
||||
PossibleSteps []NextStep
|
||||
PasswordVerified bool
|
||||
MFAsVerified []MFAType
|
||||
Audience []string
|
||||
AuthTime time.Time
|
||||
Code string
|
||||
LoginPolicy *LoginPolicy
|
||||
AllowedExternalIDPs []*IDPProvider
|
||||
LabelPolicy *LabelPolicy
|
||||
}
|
||||
|
||||
type ExternalUser struct {
|
||||
@ -103,8 +108,9 @@ func (a *AuthRequest) WithCurrentInfo(info *BrowserInfo) *AuthRequest {
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *AuthRequest) SetUserInfo(userID, loginName, displayName, userOrgID string) {
|
||||
func (a *AuthRequest) SetUserInfo(userID, userName, loginName, displayName, userOrgID string) {
|
||||
a.UserID = userID
|
||||
a.UserName = userName
|
||||
a.LoginName = loginName
|
||||
a.DisplayName = displayName
|
||||
a.UserOrgID = userOrgID
|
||||
|
@ -1,11 +1,11 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Human struct {
|
||||
@ -59,9 +59,6 @@ func (u *Human) CheckOrgIAMPolicy(policy *OrgIAMPolicy) error {
|
||||
if policy == nil {
|
||||
return caos_errors.ThrowPreconditionFailed(nil, "DOMAIN-zSH7j", "Errors.Users.OrgIamPolicyNil")
|
||||
}
|
||||
if policy.UserLoginMustBeDomain && strings.Contains(u.Username, "@") {
|
||||
return caos_errors.ThrowPreconditionFailed(nil, "DOMAIN-se4sJ", "Errors.User.EmailAsUsernameNotAllowed")
|
||||
}
|
||||
if !policy.UserLoginMustBeDomain && u.Profile != nil && u.Username == "" && u.Email != nil {
|
||||
u.Username = u.EmailAddress
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ func (s *SelectUserStep) Type() NextStepType {
|
||||
|
||||
type UserSelection struct {
|
||||
UserID string
|
||||
UserName string
|
||||
DisplayName string
|
||||
LoginName string
|
||||
UserSessionState UserSessionState
|
||||
|
@ -7,9 +7,10 @@ import (
|
||||
type LabelPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Default bool
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
Default bool
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
HideLoginNameSuffix bool
|
||||
}
|
||||
|
||||
func (p *LabelPolicy) IsValid() bool {
|
||||
|
@ -7,10 +7,11 @@ import (
|
||||
type LabelPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
Default bool
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
State PolicyState
|
||||
Default bool
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
HideLoginNameSuffix bool
|
||||
}
|
||||
|
||||
func (p *LabelPolicy) IsValid() bool {
|
||||
|
@ -6,10 +6,11 @@ import (
|
||||
)
|
||||
|
||||
type LabelPolicyView struct {
|
||||
AggregateID string
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
Default bool
|
||||
AggregateID string
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
HideLoginNameSuffix bool
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
|
@ -10,26 +10,29 @@ import (
|
||||
|
||||
type LabelPolicy struct {
|
||||
es_models.ObjectRoot
|
||||
State int32 `json:"-"`
|
||||
PrimaryColor string `json:"primaryColor"`
|
||||
SecondaryColor string `json:"secondaryColor"`
|
||||
State int32 `json:"-"`
|
||||
PrimaryColor string `json:"primaryColor"`
|
||||
SecondaryColor string `json:"secondaryColor"`
|
||||
HideLoginNameSuffix bool `json:"hideLoginNameSuffix"`
|
||||
}
|
||||
|
||||
func LabelPolicyToModel(policy *LabelPolicy) *iam_model.LabelPolicy {
|
||||
return &iam_model.LabelPolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
State: iam_model.PolicyState(policy.State),
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
State: iam_model.PolicyState(policy.State),
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||
}
|
||||
}
|
||||
|
||||
func LabelPolicyFromModel(policy *iam_model.LabelPolicy) *LabelPolicy {
|
||||
return &LabelPolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
State: int32(policy.State),
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
State: int32(policy.State),
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
|
||||
es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
@ -24,34 +25,39 @@ type LabelPolicyView struct {
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
State int32 `json:"-" gorm:"column:label_policy_state"`
|
||||
|
||||
PrimaryColor string `json:"primaryColor" gorm:"column:primary_color"`
|
||||
SecondaryColor string `json:"secondaryColor" gorm:"column:secondary_color"`
|
||||
Default bool `json:"-" gorm:"-"`
|
||||
PrimaryColor string `json:"primaryColor" gorm:"column:primary_color"`
|
||||
SecondaryColor string `json:"secondaryColor" gorm:"column:secondary_color"`
|
||||
HideLoginNameSuffix bool `json:"hideLoginNameSuffix" gorm:"column:hide_login_name_suffix"`
|
||||
Default bool `json:"-" gorm:"-"`
|
||||
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func LabelPolicyViewFromModel(policy *model.LabelPolicyView) *LabelPolicyView {
|
||||
return &LabelPolicyView{
|
||||
AggregateID: policy.AggregateID,
|
||||
Sequence: policy.Sequence,
|
||||
CreationDate: policy.CreationDate,
|
||||
ChangeDate: policy.ChangeDate,
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
Default: policy.Default,
|
||||
func (p *LabelPolicyView) ToDomain() *domain.LabelPolicy {
|
||||
return &domain.LabelPolicy{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: p.AggregateID,
|
||||
CreationDate: p.CreationDate,
|
||||
ChangeDate: p.ChangeDate,
|
||||
Sequence: p.Sequence,
|
||||
},
|
||||
Default: p.Default,
|
||||
PrimaryColor: p.PrimaryColor,
|
||||
SecondaryColor: p.SecondaryColor,
|
||||
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
||||
}
|
||||
}
|
||||
|
||||
func LabelPolicyViewToModel(policy *LabelPolicyView) *model.LabelPolicyView {
|
||||
return &model.LabelPolicyView{
|
||||
AggregateID: policy.AggregateID,
|
||||
Sequence: policy.Sequence,
|
||||
CreationDate: policy.CreationDate,
|
||||
ChangeDate: policy.ChangeDate,
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
Default: policy.Default,
|
||||
AggregateID: policy.AggregateID,
|
||||
Sequence: policy.Sequence,
|
||||
CreationDate: policy.CreationDate,
|
||||
ChangeDate: policy.ChangeDate,
|
||||
PrimaryColor: policy.PrimaryColor,
|
||||
SecondaryColor: policy.SecondaryColor,
|
||||
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||
Default: policy.Default,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,6 +199,32 @@ func (repo *OrgRepository) GetLabelPolicy(ctx context.Context) (*iam_model.Label
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), err
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
|
||||
policy, viewErr := repo.View.LabelPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
if viewErr != nil && !errors.IsNotFound(viewErr) {
|
||||
return nil, viewErr
|
||||
}
|
||||
if errors.IsNotFound(viewErr) {
|
||||
policy = new(iam_es_model.LabelPolicyView)
|
||||
}
|
||||
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
|
||||
if errors.IsNotFound(viewErr) && len(events) == 0 {
|
||||
return nil, errors.ThrowNotFound(nil, "EVENT-3Nf8sd", "Errors.IAM.LabelPolicy.NotFound")
|
||||
}
|
||||
if esErr != nil {
|
||||
logging.Log("EVENT-28uLp").WithError(esErr).Debug("error retrieving new events")
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), nil
|
||||
}
|
||||
policyCopy := *policy
|
||||
for _, event := range events {
|
||||
if err := policyCopy.AppendEvent(event); err != nil {
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), nil
|
||||
}
|
||||
}
|
||||
policy.Default = true
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), nil
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) GetLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
|
||||
policy, viewErr := repo.View.LoginPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if viewErr != nil && !errors.IsNotFound(viewErr) {
|
||||
|
@ -45,4 +45,7 @@ type OrgRepository interface {
|
||||
|
||||
GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
||||
GetMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
||||
|
||||
GetLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ func NewLabelPolicyAddedEvent(
|
||||
aggregate *eventstore.Aggregate,
|
||||
primaryColor,
|
||||
secondaryColor string,
|
||||
hideLoginNameSuffix bool,
|
||||
) *LabelPolicyAddedEvent {
|
||||
return &LabelPolicyAddedEvent{
|
||||
LabelPolicyAddedEvent: *policy.NewLabelPolicyAddedEvent(
|
||||
@ -30,7 +31,8 @@ func NewLabelPolicyAddedEvent(
|
||||
aggregate,
|
||||
LabelPolicyAddedEventType),
|
||||
primaryColor,
|
||||
secondaryColor),
|
||||
secondaryColor,
|
||||
hideLoginNameSuffix),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ func NewLabelPolicyAddedEvent(
|
||||
aggregate *eventstore.Aggregate,
|
||||
primaryColor,
|
||||
secondaryColor string,
|
||||
hideLoginNameSuffix bool,
|
||||
) *LabelPolicyAddedEvent {
|
||||
return &LabelPolicyAddedEvent{
|
||||
LabelPolicyAddedEvent: *policy.NewLabelPolicyAddedEvent(
|
||||
@ -31,7 +32,8 @@ func NewLabelPolicyAddedEvent(
|
||||
aggregate,
|
||||
LabelPolicyAddedEventType),
|
||||
primaryColor,
|
||||
secondaryColor),
|
||||
secondaryColor,
|
||||
hideLoginNameSuffix),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,9 @@ const (
|
||||
type LabelPolicyAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
PrimaryColor string `json:"primaryColor,omitempty"`
|
||||
SecondaryColor string `json:"secondaryColor,omitempty"`
|
||||
PrimaryColor string `json:"primaryColor,omitempty"`
|
||||
SecondaryColor string `json:"secondaryColor,omitempty"`
|
||||
HideLoginNameSuffix bool `json:"hideLoginNameSuffix,omitempty"`
|
||||
}
|
||||
|
||||
func (e *LabelPolicyAddedEvent) Data() interface{} {
|
||||
@ -32,12 +33,14 @@ func NewLabelPolicyAddedEvent(
|
||||
base *eventstore.BaseEvent,
|
||||
primaryColor,
|
||||
secondaryColor string,
|
||||
hideLoginNameSuffix bool,
|
||||
) *LabelPolicyAddedEvent {
|
||||
|
||||
return &LabelPolicyAddedEvent{
|
||||
BaseEvent: *base,
|
||||
PrimaryColor: primaryColor,
|
||||
SecondaryColor: secondaryColor,
|
||||
BaseEvent: *base,
|
||||
PrimaryColor: primaryColor,
|
||||
SecondaryColor: secondaryColor,
|
||||
HideLoginNameSuffix: hideLoginNameSuffix,
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,8 +60,9 @@ func LabelPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReade
|
||||
type LabelPolicyChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
PrimaryColor *string `json:"primaryColor,omitempty"`
|
||||
SecondaryColor *string `json:"secondaryColor,omitempty"`
|
||||
PrimaryColor *string `json:"primaryColor,omitempty"`
|
||||
SecondaryColor *string `json:"secondaryColor,omitempty"`
|
||||
HideLoginNameSuffix *bool `json:"hideLoginNameSuffix,omitempty"`
|
||||
}
|
||||
|
||||
func (e *LabelPolicyChangedEvent) Data() interface{} {
|
||||
@ -99,6 +103,12 @@ func ChangeSecondaryColor(secondaryColor string) func(*LabelPolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeHideLoginNameSuffix(hideLoginNameSuffix bool) func(*LabelPolicyChangedEvent) {
|
||||
return func(e *LabelPolicyChangedEvent) {
|
||||
e.HideLoginNameSuffix = &hideLoginNameSuffix
|
||||
}
|
||||
}
|
||||
|
||||
func LabelPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
e := &LabelPolicyChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
|
@ -54,7 +54,8 @@ func (l *Login) handleLoginNameCheck(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||
err = l.authRepo.CheckLoginName(r.Context(), authReq.ID, data.LoginName, userAgentID)
|
||||
loginName := data.LoginName
|
||||
err = l.authRepo.CheckLoginName(r.Context(), authReq.ID, loginName, userAgentID)
|
||||
if err != nil {
|
||||
l.renderLogin(w, r, authReq, err)
|
||||
return
|
||||
@ -73,7 +74,7 @@ func (l *Login) renderLogin(w http.ResponseWriter, r *http.Request, authReq *dom
|
||||
return authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowUsernamePassword
|
||||
},
|
||||
"hasExternalLogin": func() bool {
|
||||
return authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
|
||||
return authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
|
||||
},
|
||||
}
|
||||
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplLogin], data, funcs)
|
||||
|
@ -265,15 +265,17 @@ func (l *Login) getBaseData(r *http.Request, authReq *domain.AuthRequest, title
|
||||
ErrType: errType,
|
||||
ErrMessage: errMessage,
|
||||
},
|
||||
Lang: l.renderer.Lang(r).String(),
|
||||
Title: title,
|
||||
Theme: l.getTheme(r),
|
||||
ThemeMode: l.getThemeMode(r),
|
||||
OrgID: l.getOrgID(authReq),
|
||||
OrgName: l.getOrgName(authReq),
|
||||
AuthReqID: getRequestID(authReq, r),
|
||||
CSRF: csrf.TemplateField(r),
|
||||
Nonce: http_mw.GetNonce(r),
|
||||
Lang: l.renderer.Lang(r).String(),
|
||||
Title: title,
|
||||
Theme: l.getTheme(r),
|
||||
ThemeMode: l.getThemeMode(r),
|
||||
OrgID: l.getOrgID(authReq),
|
||||
OrgName: l.getOrgName(authReq),
|
||||
PrimaryDomain: l.getOrgPrimaryDomain(authReq),
|
||||
DisplayLoginNameSuffix: l.isDisplayLoginNameSuffix(authReq),
|
||||
AuthReqID: getRequestID(authReq, r),
|
||||
CSRF: csrf.TemplateField(r),
|
||||
Nonce: http_mw.GetNonce(r),
|
||||
}
|
||||
if authReq != nil {
|
||||
baseData.LoginPolicy = authReq.LoginPolicy
|
||||
@ -283,12 +285,14 @@ func (l *Login) getBaseData(r *http.Request, authReq *domain.AuthRequest, title
|
||||
}
|
||||
|
||||
func (l *Login) getProfileData(authReq *domain.AuthRequest) profileData {
|
||||
var loginName, displayName string
|
||||
var userName, loginName, displayName string
|
||||
if authReq != nil {
|
||||
userName = authReq.UserName
|
||||
loginName = authReq.LoginName
|
||||
displayName = authReq.DisplayName
|
||||
}
|
||||
return profileData{
|
||||
UserName: userName,
|
||||
LoginName: loginName,
|
||||
DisplayName: displayName,
|
||||
}
|
||||
@ -329,6 +333,23 @@ func (l *Login) getOrgName(authReq *domain.AuthRequest) string {
|
||||
return authReq.RequestedOrgName
|
||||
}
|
||||
|
||||
func (l *Login) getOrgPrimaryDomain(authReq *domain.AuthRequest) string {
|
||||
if authReq == nil {
|
||||
return ""
|
||||
}
|
||||
return authReq.RequestedPrimaryDomain
|
||||
}
|
||||
|
||||
func (l *Login) isDisplayLoginNameSuffix(authReq *domain.AuthRequest) bool {
|
||||
if authReq == nil {
|
||||
return false
|
||||
}
|
||||
if authReq.RequestedOrgID == "" {
|
||||
return false
|
||||
}
|
||||
return authReq.LabelPolicy != nil && !authReq.LabelPolicy.HideLoginNameSuffix
|
||||
}
|
||||
|
||||
func getRequestID(authReq *domain.AuthRequest, r *http.Request) string {
|
||||
if authReq != nil {
|
||||
return authReq.ID
|
||||
@ -351,17 +372,19 @@ func (l *Login) cspErrorHandler(err error) http.Handler {
|
||||
|
||||
type baseData struct {
|
||||
errorData
|
||||
Lang string
|
||||
Title string
|
||||
Theme string
|
||||
ThemeMode string
|
||||
OrgID string
|
||||
OrgName string
|
||||
AuthReqID string
|
||||
CSRF template.HTML
|
||||
Nonce string
|
||||
LoginPolicy *domain.LoginPolicy
|
||||
IDPProviders []*domain.IDPProvider
|
||||
Lang string
|
||||
Title string
|
||||
Theme string
|
||||
ThemeMode string
|
||||
OrgID string
|
||||
OrgName string
|
||||
PrimaryDomain string
|
||||
DisplayLoginNameSuffix bool
|
||||
AuthReqID string
|
||||
CSRF template.HTML
|
||||
Nonce string
|
||||
LoginPolicy *domain.LoginPolicy
|
||||
IDPProviders []*domain.IDPProvider
|
||||
}
|
||||
|
||||
type errorData struct {
|
||||
@ -380,6 +403,7 @@ type userData struct {
|
||||
|
||||
type profileData struct {
|
||||
LoginName string
|
||||
UserName string
|
||||
DisplayName string
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,10 @@
|
||||
Password:
|
||||
Title: Willkommen zurück!
|
||||
Description: Gib deine Benutzerdaten ein.
|
||||
Password: Passwort
|
||||
MinLength: Mindestlänge
|
||||
HasUppercase: Grossbuchstaben
|
||||
HasLowercase: Kleinbuchstaben
|
||||
HasNumber: Nummer
|
||||
HasSymbol: Symbol
|
||||
|
||||
Login:
|
||||
Title: Anmeldung
|
||||
Description: Mit ZITADEL-Konto anmelden.
|
||||
TitleLinking: Anmeldung für Benutzer Linking
|
||||
DescriptionLinking: Gib deine Benutzerdaten ein um den externen Benutzer mit einem ZITADEL Benutzer zu linken.
|
||||
Loginname: Loginname
|
||||
UsernamePlaceHolder: username
|
||||
LoginnamePlaceHolder: username@domain
|
||||
ExternalLogin: Melde dich mit einem externen Benutzer an
|
||||
MustBeMemberOfOrg: Der Benutzer muss der Organisation {{.OrgName}} angehören.
|
||||
@ -28,6 +19,16 @@ UserSelection:
|
||||
SessionState1: inaktiv
|
||||
MustBeMemberOfOrg: Der Benutzer muss der Organisation {{.OrgName}} angehören.
|
||||
|
||||
Password:
|
||||
Title: Willkommen zurück!
|
||||
Description: Gib deine Benutzerdaten ein.
|
||||
Password: Passwort
|
||||
MinLength: Mindestlänge
|
||||
HasUppercase: Grossbuchstaben
|
||||
HasLowercase: Kleinbuchstaben
|
||||
HasNumber: Nummer
|
||||
HasSymbol: Symbol
|
||||
|
||||
UsernameChange:
|
||||
Title: Usernamen ändern
|
||||
Description: Wähle deinen neuen Benutzernamen
|
||||
|
@ -4,9 +4,10 @@ Login:
|
||||
TitleLinking: Login for userlinking
|
||||
DescriptionLinking: Enter your login data to link your external user with a ZITADEL user.
|
||||
Loginname: Loginname
|
||||
UsernamePlaceHolder: username
|
||||
LoginnamePlaceHolder: username@domain
|
||||
ExternalLogin: Login with an external user.
|
||||
MustBeMemberOfOrg: The user must be mermber of the {{.OrgDomain}} organisation.
|
||||
MustBeMemberOfOrg: The user must be mermber of the {{.OrgName}} organisation.
|
||||
|
||||
UserSelection:
|
||||
Title: Select account
|
||||
@ -16,7 +17,7 @@ UserSelection:
|
||||
OtherUser: Other User
|
||||
SessionState0: active
|
||||
SessionState1: inactive
|
||||
MustBeMemberOfOrg: The user must be mermber of the {{.OrgDomain}} organisation.
|
||||
MustBeMemberOfOrg: The user must be mermber of the {{.OrgName}} organisation.
|
||||
|
||||
Password:
|
||||
Title: Password
|
||||
|
@ -12,6 +12,11 @@ $lgn-container-margin: 0px auto 50px auto;
|
||||
align-items: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.left {
|
||||
padding: .5rem 1rem;
|
||||
|
@ -25,7 +25,6 @@
|
||||
color: inherit;
|
||||
background: transparent;
|
||||
box-shadow: inset 0 -1px lgn-color($foreground, footer-line);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
$primary: map-get($config, primary);
|
||||
|
@ -440,6 +440,10 @@ i {
|
||||
align-items: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lgn-account-selection .lgn-account:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.lgn-account-selection .lgn-account .left {
|
||||
padding: 0.5rem 1rem;
|
||||
@ -1298,6 +1302,10 @@ i {
|
||||
align-items: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lgn-account-selection .lgn-account:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.lgn-account-selection .lgn-account .left {
|
||||
padding: 0.5rem 1rem;
|
||||
|
File diff suppressed because one or more lines are too long
@ -440,6 +440,10 @@ i {
|
||||
align-items: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lgn-account-selection .lgn-account:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.lgn-account-selection .lgn-account .left {
|
||||
padding: 0.5rem 1rem;
|
||||
@ -1202,7 +1206,6 @@ a:hover, a:active {
|
||||
color: inherit;
|
||||
background: transparent;
|
||||
box-shadow: inset 0 -1px #303131;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lgn-account-selection .lgn-account:hover {
|
||||
background-color: rgba(255, 255, 255, 0.02);
|
||||
@ -1522,7 +1525,6 @@ a:hover, a:active {
|
||||
color: inherit;
|
||||
background: transparent;
|
||||
box-shadow: inset 0 -1px #303131;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lgn-dark-theme .lgn-account-selection .lgn-account:hover {
|
||||
background-color: rgba(255, 255, 255, 0.02);
|
||||
@ -1836,7 +1838,6 @@ a:hover, a:active {
|
||||
color: inherit;
|
||||
background: transparent;
|
||||
box-shadow: inset 0 -1px #e3e8ee;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lgn-light-theme .lgn-account-selection .lgn-account:hover {
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
|
File diff suppressed because one or more lines are too long
@ -20,8 +20,13 @@
|
||||
{{if hasUsernamePasswordLogin }}
|
||||
<div class="fields">
|
||||
<label class="lgn-label" for="loginName">{{t "Login.Loginname"}}</label>
|
||||
<input class="lgn-input lgn-suffix-input" type="text" id="loginName" name="loginName" placeholder="{{t "Login.LoginnamePlaceHolder"}}"
|
||||
value="{{ .LoginName }}" {{if .ErrMessage}}shake {{end}} autocomplete="username" autofocus required>
|
||||
<div class="lgn-suffix-wrapper">
|
||||
<input class="lgn-input lgn-suffix-input" type="text" id="loginName" name="loginName" placeholder="{{if .OrgID }}{{t "Login.UsernamePlaceHolder"}}{{else}}{{t "Login.LoginnamePlaceHolder"}}{{end}}"
|
||||
value="{{ .UserName }}" {{if .ErrMessage}}shake {{end}} autocomplete="username" autofocus required>
|
||||
{{if .DisplayLoginNameSuffix}}
|
||||
<span id="default-login-suffix" lgnsuffix class="loginname-suffix">@{{.PrimaryDomain}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@ -53,5 +58,6 @@
|
||||
|
||||
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
|
||||
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
|
||||
<script src="{{ resourceUrl "scripts/input_suffix_offset.js" }}"></script>
|
||||
|
||||
{{template "main-bottom" .}}
|
@ -23,10 +23,11 @@
|
||||
|
||||
<div class="lgn-account-selection">
|
||||
{{ if .Users }}
|
||||
{{ $displayLoginNameSuffix := and .OrgID (not .DisplayLoginNameSuffix)}}
|
||||
{{ range $user := .Users }}
|
||||
{{ $sessionState := (printf "UserSelection.SessionState%v" $user.UserSessionState) }}
|
||||
<button type="submit" name="userID" value="{{$user.UserID}}" class="lgn-account"
|
||||
{{if not $user.SelectionPossible}}disabled title="{{t " Errors.User.NotAllowedOrg"}}"{{end}}>
|
||||
{{if not $user.SelectionPossible}}disabled title="{{t "Errors.User.NotAllowedOrg"}}"{{end}}>
|
||||
<div class="left">
|
||||
<div class="lgn-avatar" displayname="{{$user.DisplayName}}">
|
||||
<span class="initials">A</span>
|
||||
@ -34,7 +35,7 @@
|
||||
</div>
|
||||
<div class="lgn-names">
|
||||
<p class="lgn-displayname">{{$user.DisplayName}}</p>
|
||||
<p class="lgn-loginname">{{$user.LoginName}}</p>
|
||||
<p class="lgn-loginname">{{if and $displayLoginNameSuffix $user.SelectionPossible}}{{$user.UserName}}{{else}}{{$user.LoginName}}{{end}}</p>
|
||||
<p class="lgn-session-state i{{$user.UserSessionState}}">{{t $sessionState}}</p>
|
||||
</div>
|
||||
<span class="fill-space"></span>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{{define "user-profile"}}
|
||||
{{if .LoginName}}
|
||||
{{if or .LoginName .UserName}}
|
||||
<div class="lgn-login-profile">
|
||||
<div class="lgn-profile-image"></div>
|
||||
<div class="lgn-names">
|
||||
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="lgn-loginname">
|
||||
<p>{{.LoginName}}</p>
|
||||
<p>{{if .DisplayLoginNameSuffix}}{{.LoginName}}{{else}}{{.UserName}}{{end}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
21
migrations/cockroach/V1.33__label_policy.sql
Normal file
21
migrations/cockroach/V1.33__label_policy.sql
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
ALTER TABLE management.label_policies ADD COLUMN hide_login_name_suffix BOOLEAN;
|
||||
ALTER TABLE adminapi.label_policies ADD COLUMN hide_login_name_suffix BOOLEAN;
|
||||
|
||||
|
||||
CREATE TABLE auth.label_policies (
|
||||
aggregate_id TEXT,
|
||||
|
||||
creation_date TIMESTAMPTZ,
|
||||
change_date TIMESTAMPTZ,
|
||||
label_policy_state SMALLINT,
|
||||
sequence BIGINT,
|
||||
|
||||
primary_color TEXT,
|
||||
secondary_color TEXT,
|
||||
hide_login_name_suffix BOOLEAN,
|
||||
|
||||
PRIMARY KEY (aggregate_id)
|
||||
);
|
||||
|
||||
GRANT SELECT ON TABLE auth.label_policies TO notification;
|
@ -1,7 +0,0 @@
|
||||
CREATE TABLE eventstore.unique_constraints (
|
||||
unique_type TEXT,
|
||||
unique_field TEXT,
|
||||
PRIMARY KEY (unique_type, unique_field)
|
||||
);
|
||||
|
||||
GRANT DELETE ON TABLE eventstore.unique_constraints to eventstore;
|
23
migrations/cockroach/V1.34__new_eventstore.sql
Normal file
23
migrations/cockroach/V1.34__new_eventstore.sql
Normal file
@ -0,0 +1,23 @@
|
||||
CREATE TABLE eventstore.unique_constraints (
|
||||
unique_type TEXT,
|
||||
unique_field TEXT,
|
||||
PRIMARY KEY (unique_type, unique_field)
|
||||
);
|
||||
|
||||
GRANT DELETE ON TABLE eventstore.unique_constraints to eventstore;
|
||||
|
||||
ALTER TABLE management.login_policies ADD COLUMN default_policy BOOLEAN;
|
||||
ALTER TABLE adminapi.login_policies ADD COLUMN default_policy BOOLEAN;
|
||||
ALTER TABLE auth.login_policies ADD COLUMN default_policy BOOLEAN;
|
||||
|
||||
CREATE INDEX event_type ON eventstore.events (event_type);
|
||||
CREATE INDEX resource_owner ON eventstore.events (resource_owner);
|
||||
|
||||
CREATE USER queries WITH PASSWORD ${queriespassword};
|
||||
GRANT SELECT ON TABLE eventstore.events TO queries;
|
||||
|
||||
ALTER TABLE management.org_members ADD COLUMN preferred_login_name TEXT;
|
||||
ALTER TABLE management.project_members ADD COLUMN preferred_login_name TEXT;
|
||||
ALTER TABLE management.project_grant_members ADD COLUMN preferred_login_name TEXT;
|
||||
|
||||
ALTER TABLE adminapi.iam_members ADD COLUMN preferred_login_name TEXT;
|
@ -1,3 +0,0 @@
|
||||
ALTER TABLE management.login_policies ADD COLUMN default_policy BOOLEAN;
|
||||
ALTER TABLE adminapi.login_policies ADD COLUMN default_policy BOOLEAN;
|
||||
ALTER TABLE auth.login_policies ADD COLUMN default_policy BOOLEAN;
|
@ -1,2 +0,0 @@
|
||||
CREATE INDEX event_type ON eventstore.events (event_type);
|
||||
CREATE INDEX resource_owner ON eventstore.events (resource_owner);
|
@ -1,2 +0,0 @@
|
||||
CREATE USER queries WITH PASSWORD ${queriespassword};
|
||||
GRANT SELECT ON TABLE eventstore.events TO queries;
|
@ -1,5 +0,0 @@
|
||||
ALTER TABLE management.org_members ADD COLUMN preferred_login_name TEXT;
|
||||
ALTER TABLE management.project_members ADD COLUMN preferred_login_name TEXT;
|
||||
ALTER TABLE management.project_grant_members ADD COLUMN preferred_login_name TEXT;
|
||||
|
||||
ALTER TABLE adminapi.iam_members ADD COLUMN preferred_login_name TEXT;
|
@ -755,6 +755,7 @@ message GetLabelPolicyResponse {
|
||||
message UpdateLabelPolicyRequest {
|
||||
string primary_color = 1 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
||||
string secondary_color = 2 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
||||
bool hide_login_name_suffix = 3;
|
||||
}
|
||||
|
||||
message UpdateLabelPolicyResponse {
|
||||
|
@ -162,6 +162,17 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc ImportHumanUser(ImportHumanUserRequest) returns (ImportHumanUserResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/users/human/_import"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "user.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc AddMachineUser(AddMachineUserRequest) returns (AddMachineUserResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/users/machine"
|
||||
@ -1641,6 +1652,58 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetLabelPolicy(GetLabelPolicyRequest) returns (GetLabelPolicyResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/policies/label"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetDefaultLabelPolicy(GetDefaultLabelPolicyRequest) returns (GetDefaultLabelPolicyResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/policies/default/label"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc AddCustomLabelPolicy(AddCustomLabelPolicyRequest) returns (AddCustomLabelPolicyResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/policies/label"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc UpdateCustomLabelPolicy(UpdateCustomLabelPolicyRequest) returns (UpdateCustomLabelPolicyResponse) {
|
||||
option (google.api.http) = {
|
||||
put: "/policies/label"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc ResetLabelPolicyToDefault(ResetLabelPolicyToDefaultRequest) returns (ResetLabelPolicyToDefaultResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/policies/label"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "policy.delete"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetOrgIDPByID(GetOrgIDPByIDRequest) returns (GetOrgIDPByIDResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/idps/{id}"
|
||||
@ -1825,6 +1888,39 @@ message AddHumanUserResponse {
|
||||
zitadel.v1.ObjectDetails details = 2;
|
||||
}
|
||||
|
||||
message ImportHumanUserRequest {
|
||||
message Profile {
|
||||
string first_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string last_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string nick_name = 3 [(validate.rules).string = {max_len: 200}];
|
||||
string display_name = 4 [(validate.rules).string = {max_len: 200}];
|
||||
string preferred_language = 5 [(validate.rules).string = {max_len: 10}];
|
||||
zitadel.user.v1.Gender gender = 6;
|
||||
}
|
||||
message Email {
|
||||
string email = 1 [(validate.rules).string.email = true]; //TODO: check if no value is allowed
|
||||
bool is_email_verified = 2;
|
||||
}
|
||||
message Phone {
|
||||
// has to be a global number
|
||||
string phone = 1 [(validate.rules).string = {min_len: 1, max_len: 50, prefix: "+"}];
|
||||
bool is_phone_verified = 2;
|
||||
}
|
||||
|
||||
string user_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
|
||||
Profile profile = 2 [(validate.rules).message.required = true];
|
||||
Email email = 3 [(validate.rules).message.required = true];
|
||||
Phone phone = 4;
|
||||
string password = 5;
|
||||
bool password_change_required = 6;
|
||||
}
|
||||
|
||||
message ImportHumanUserResponse {
|
||||
string user_id = 1;
|
||||
zitadel.v1.ObjectDetails details = 2;
|
||||
}
|
||||
|
||||
message AddMachineUserRequest {
|
||||
string user_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
|
||||
@ -3097,6 +3193,45 @@ message ResetPasswordLockoutPolicyToDefaultResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
message GetLabelPolicyRequest {}
|
||||
|
||||
message GetLabelPolicyResponse {
|
||||
zitadel.policy.v1.LabelPolicy policy = 1;
|
||||
bool is_default = 2;
|
||||
}
|
||||
|
||||
message GetDefaultLabelPolicyRequest {}
|
||||
|
||||
message GetDefaultLabelPolicyResponse {
|
||||
zitadel.policy.v1.LabelPolicy policy = 1;
|
||||
}
|
||||
|
||||
message AddCustomLabelPolicyRequest {
|
||||
string primary_color = 1 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
||||
string secondary_color = 2 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
||||
bool hide_login_name_suffix = 3;
|
||||
}
|
||||
|
||||
message AddCustomLabelPolicyResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
message UpdateCustomLabelPolicyRequest {
|
||||
string primary_color = 1 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
||||
string secondary_color = 2 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
||||
bool hide_login_name_suffix = 3;
|
||||
}
|
||||
|
||||
message UpdateCustomLabelPolicyResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
message ResetLabelPolicyToDefaultRequest {}
|
||||
|
||||
message ResetLabelPolicyToDefaultResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
message GetOrgIDPByIDRequest {
|
||||
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ message LabelPolicy {
|
||||
string primary_color = 2;
|
||||
string secondary_color = 3;
|
||||
bool is_default = 4;
|
||||
bool hide_login_name_suffix = 5;
|
||||
}
|
||||
|
||||
message LoginPolicy {
|
||||
|
Loading…
Reference in New Issue
Block a user