mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-12 13:18:31 +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 commit 03ddb8fc388494d6ec99b1db9e16d16c28ee9649) * 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 commit 03ddb8fc388494d6ec99b1db9e16d16c28ee9649) * 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 commit 03ddb8fc388494d6ec99b1db9e16d16c28ee9649) * 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 {
|
func updateLabelPolicyToDomain(policy *admin_pb.UpdateLabelPolicyRequest) *domain.LabelPolicy {
|
||||||
return &domain.LabelPolicy{
|
return &domain.LabelPolicy{
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
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
|
}, 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) {
|
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))
|
machine, err := s.command.AddMachine(ctx, authz.GetCtxData(ctx).OrgID, AddMachineUserRequestToDomain(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -69,6 +69,38 @@ func AddHumanUserRequestToDomain(req *mgmt_pb.AddHumanUserRequest) *domain.Human
|
|||||||
return h
|
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 {
|
func AddMachineUserRequestToDomain(req *mgmt_pb.AddMachineUserRequest) *domain.Machine {
|
||||||
return &domain.Machine{
|
return &domain.Machine{
|
||||||
Username: req.UserName,
|
Username: req.UserName,
|
||||||
|
@ -8,9 +8,10 @@ import (
|
|||||||
|
|
||||||
func ModelLabelPolicyToPb(policy *model.LabelPolicyView) *policy_pb.LabelPolicy {
|
func ModelLabelPolicyToPb(policy *model.LabelPolicyView) *policy_pb.LabelPolicy {
|
||||||
return &policy_pb.LabelPolicy{
|
return &policy_pb.LabelPolicy{
|
||||||
IsDefault: policy.Default,
|
IsDefault: policy.Default,
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
SecondaryColor: policy.SecondaryColor,
|
||||||
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
Details: object.ToViewDetailsPb(
|
Details: object.ToViewDetailsPb(
|
||||||
policy.Sequence,
|
policy.Sequence,
|
||||||
policy.CreationDate,
|
policy.CreationDate,
|
||||||
|
@ -244,7 +244,7 @@ func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAge
|
|||||||
if request.RequestedOrgID != "" && request.RequestedOrgID != user.ResourceOwner {
|
if request.RequestedOrgID != "" && request.RequestedOrgID != user.ResourceOwner {
|
||||||
return errors.ThrowPreconditionFailed(nil, "EVENT-fJe2a", "Errors.User.NotAllowedOrg")
|
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)
|
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,21 +425,30 @@ func (repo *AuthRequestRepo) fillLoginPolicy(ctx context.Context, request *domai
|
|||||||
orgID = repo.IAMID
|
orgID = repo.IAMID
|
||||||
}
|
}
|
||||||
|
|
||||||
policy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, orgID)
|
loginPolicy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
request.LoginPolicy = policy
|
request.LoginPolicy = loginPolicy
|
||||||
if idpProviders != nil {
|
if idpProviders != nil {
|
||||||
request.AllowedExternalIDPs = idpProviders
|
request.AllowedExternalIDPs = idpProviders
|
||||||
}
|
}
|
||||||
|
labelPolicy, err := repo.getLabelPolicy(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
request.LabelPolicy = labelPolicy
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain.AuthRequest, loginName string) (err error) {
|
func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain.AuthRequest, loginName string) (err error) {
|
||||||
user := new(user_view_model.UserView)
|
user := new(user_view_model.UserView)
|
||||||
if request.RequestedOrgID != "" {
|
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 {
|
} else {
|
||||||
user, err = repo.View.UserByLoginName(loginName)
|
user, err = repo.View.UserByLoginName(loginName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -453,7 +462,7 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
request.SetUserInfo(user.ID, loginName, "", user.ResourceOwner)
|
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", user.ResourceOwner)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +505,7 @@ func (repo *AuthRequestRepo) checkExternalUserLogin(request *domain.AuthRequest,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
request.SetUserInfo(externalIDP.UserID, "", "", externalIDP.ResourceOwner)
|
request.SetUserInfo(externalIDP.UserID, "", "", "", externalIDP.ResourceOwner)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -599,6 +608,7 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *domain.AuthRequest)
|
|||||||
users[i] = domain.UserSelection{
|
users[i] = domain.UserSelection{
|
||||||
UserID: session.UserID,
|
UserID: session.UserID,
|
||||||
DisplayName: session.DisplayName,
|
DisplayName: session.DisplayName,
|
||||||
|
UserName: session.UserName,
|
||||||
LoginName: session.LoginName,
|
LoginName: session.LoginName,
|
||||||
UserSessionState: auth_req_model.UserSessionStateToDomain(session.State),
|
UserSessionState: auth_req_model.UserSessionStateToDomain(session.State),
|
||||||
SelectionPossible: request.RequestedOrgID == "" || request.RequestedOrgID == session.ResourceOwner,
|
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
|
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 {
|
func setOrgID(orgViewProvider orgViewProvider, request *domain.AuthRequest) error {
|
||||||
primaryDomain := request.GetScopeOrgPrimaryDomain()
|
primaryDomain := request.GetScopeOrgPrimaryDomain()
|
||||||
if primaryDomain == "" {
|
if primaryDomain == "" {
|
||||||
@ -707,6 +732,7 @@ func setOrgID(orgViewProvider orgViewProvider, request *domain.AuthRequest) erro
|
|||||||
}
|
}
|
||||||
request.RequestedOrgID = org.ID
|
request.RequestedOrgID = org.ID
|
||||||
request.RequestedOrgName = org.Name
|
request.RequestedOrgName = org.Name
|
||||||
|
request.RequestedPrimaryDomain = primaryDomain
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
|||||||
newOrgIAMPolicy(
|
newOrgIAMPolicy(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
|
||||||
newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), 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
|
MaxAuthAge uint32
|
||||||
Request Request
|
Request Request
|
||||||
|
|
||||||
levelOfAssurance LevelOfAssurance
|
levelOfAssurance LevelOfAssurance
|
||||||
UserID string
|
UserID string
|
||||||
LoginName string
|
UserName string
|
||||||
DisplayName string
|
LoginName string
|
||||||
UserOrgID string
|
DisplayName string
|
||||||
RequestedOrgID string
|
UserOrgID string
|
||||||
RequestedOrgName string
|
RequestedOrgID string
|
||||||
SelectedIDPConfigID string
|
RequestedOrgName string
|
||||||
LinkingUsers []*ExternalUser
|
RequestedPrimaryDomain string
|
||||||
PossibleSteps []NextStep
|
SelectedIDPConfigID string
|
||||||
PasswordVerified bool
|
LinkingUsers []*ExternalUser
|
||||||
MFAsVerified []MFAType
|
PossibleSteps []NextStep
|
||||||
Audience []string
|
PasswordVerified bool
|
||||||
AuthTime time.Time
|
MFAsVerified []MFAType
|
||||||
Code string
|
Audience []string
|
||||||
LoginPolicy *model.LoginPolicyView
|
AuthTime time.Time
|
||||||
AllowedExternalIDPs []*model.IDPProviderView
|
Code string
|
||||||
|
LoginPolicy *model.LoginPolicyView
|
||||||
|
LabelPolicy *model.LabelPolicyView
|
||||||
|
AllowedExternalIDPs []*model.IDPProviderView
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExternalUser struct {
|
type ExternalUser struct {
|
||||||
@ -123,8 +126,9 @@ func (a *AuthRequest) WithCurrentInfo(info *BrowserInfo) *AuthRequest {
|
|||||||
return a
|
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.UserID = userID
|
||||||
|
a.UserName = userName
|
||||||
a.LoginName = loginName
|
a.LoginName = loginName
|
||||||
a.DisplayName = displayName
|
a.DisplayName = displayName
|
||||||
a.UserOrgID = userOrgID
|
a.UserOrgID = userOrgID
|
||||||
|
@ -54,6 +54,7 @@ func (s *SelectUserStep) Type() NextStepType {
|
|||||||
type UserSelection struct {
|
type UserSelection struct {
|
||||||
UserID string
|
UserID string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
|
UserName string
|
||||||
LoginName string
|
LoginName string
|
||||||
UserSessionState UserSessionState
|
UserSessionState UserSessionState
|
||||||
SelectionPossible bool
|
SelectionPossible bool
|
||||||
|
@ -46,9 +46,10 @@ func writeModelToLoginPolicy(wm *LoginPolicyWriteModel) *domain.LoginPolicy {
|
|||||||
|
|
||||||
func writeModelToLabelPolicy(wm *LabelPolicyWriteModel) *domain.LabelPolicy {
|
func writeModelToLabelPolicy(wm *LabelPolicyWriteModel) *domain.LabelPolicy {
|
||||||
return &domain.LabelPolicy{
|
return &domain.LabelPolicy{
|
||||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||||
PrimaryColor: wm.PrimaryColor,
|
PrimaryColor: wm.PrimaryColor,
|
||||||
SecondaryColor: wm.SecondaryColor,
|
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 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")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
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 {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ func (wm *IAMLabelPolicyWriteModel) NewChangedEvent(
|
|||||||
aggregate *eventstore.Aggregate,
|
aggregate *eventstore.Aggregate,
|
||||||
primaryColor,
|
primaryColor,
|
||||||
secondaryColor string,
|
secondaryColor string,
|
||||||
|
hideLoginNameSuffix bool,
|
||||||
) (*iam.LabelPolicyChangedEvent, bool) {
|
) (*iam.LabelPolicyChangedEvent, bool) {
|
||||||
changes := make([]policy.LabelPolicyChanges, 0)
|
changes := make([]policy.LabelPolicyChanges, 0)
|
||||||
if wm.PrimaryColor != primaryColor {
|
if wm.PrimaryColor != primaryColor {
|
||||||
@ -61,6 +62,9 @@ func (wm *IAMLabelPolicyWriteModel) NewChangedEvent(
|
|||||||
if wm.SecondaryColor != secondaryColor {
|
if wm.SecondaryColor != secondaryColor {
|
||||||
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
||||||
}
|
}
|
||||||
|
if wm.HideLoginNameSuffix != hideLoginNameSuffix {
|
||||||
|
changes = append(changes, policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix))
|
||||||
|
}
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
|||||||
&iam.NewAggregate().Aggregate,
|
&iam.NewAggregate().Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -68,8 +69,9 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
|||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -89,6 +91,7 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
|||||||
&iam.NewAggregate().Aggregate,
|
&iam.NewAggregate().Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -98,8 +101,9 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
|||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -108,8 +112,9 @@ func TestCommandSide_AddDefaultLabelPolicy(t *testing.T) {
|
|||||||
AggregateID: "IAM",
|
AggregateID: "IAM",
|
||||||
ResourceOwner: "IAM",
|
ResourceOwner: "IAM",
|
||||||
},
|
},
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -199,6 +204,7 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
|||||||
&iam.NewAggregate().Aggregate,
|
&iam.NewAggregate().Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -207,8 +213,9 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
|||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -226,13 +233,14 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
|||||||
&iam.NewAggregate().Aggregate,
|
&iam.NewAggregate().Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
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{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color-change",
|
PrimaryColor: "primary-color-change",
|
||||||
SecondaryColor: "secondary-color-change",
|
SecondaryColor: "secondary-color-change",
|
||||||
|
HideLoginNameSuffix: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -251,8 +260,9 @@ func TestCommandSide_ChangeDefaultLabelPolicy(t *testing.T) {
|
|||||||
AggregateID: "IAM",
|
AggregateID: "IAM",
|
||||||
ResourceOwner: "IAM",
|
ResourceOwner: "IAM",
|
||||||
},
|
},
|
||||||
PrimaryColor: "primary-color-change",
|
PrimaryColor: "primary-color-change",
|
||||||
SecondaryColor: "secondary-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,
|
event, _ := iam.NewLabelPolicyChangedEvent(ctx,
|
||||||
&iam.NewAggregate().Aggregate,
|
&iam.NewAggregate().Aggregate,
|
||||||
[]policy.LabelPolicyChanges{
|
[]policy.LabelPolicyChanges{
|
||||||
policy.ChangePrimaryColor(primaryColor),
|
policy.ChangePrimaryColor(primaryColor),
|
||||||
policy.ChangeSecondaryColor(secondaryColor),
|
policy.ChangeSecondaryColor(secondaryColor),
|
||||||
|
policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return event
|
return event
|
||||||
|
@ -25,7 +25,7 @@ func (c *Commands) AddLabelPolicy(ctx context.Context, resourceOwner string, pol
|
|||||||
}
|
}
|
||||||
|
|
||||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ func (c *Commands) ChangeLabelPolicy(ctx context.Context, resourceOwner string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
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 {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
|
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
|
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 == "" {
|
if orgID == "" {
|
||||||
return caos_errs.ThrowInvalidArgument(nil, "Org-Mf9sf", "Errors.ResourceOwnerMissing")
|
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-Mf9sf", "Errors.ResourceOwnerMissing")
|
||||||
}
|
}
|
||||||
existingPolicy := NewOrgLabelPolicyWriteModel(orgID)
|
existingPolicy := NewOrgLabelPolicyWriteModel(orgID)
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
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)
|
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||||
_, err = c.eventstore.PushEvents(ctx, org.NewLabelPolicyRemovedEvent(ctx, orgAgg))
|
pushedEvents, err := c.eventstore.PushEvents(ctx, org.NewLabelPolicyRemovedEvent(ctx, orgAgg))
|
||||||
return err
|
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,
|
aggregate *eventstore.Aggregate,
|
||||||
primaryColor,
|
primaryColor,
|
||||||
secondaryColor string,
|
secondaryColor string,
|
||||||
|
hideLoginNameSuffix bool,
|
||||||
) (*org.LabelPolicyChangedEvent, bool) {
|
) (*org.LabelPolicyChangedEvent, bool) {
|
||||||
changes := make([]policy.LabelPolicyChanges, 0)
|
changes := make([]policy.LabelPolicyChanges, 0)
|
||||||
if wm.PrimaryColor != primaryColor {
|
if wm.PrimaryColor != primaryColor {
|
||||||
@ -60,6 +61,9 @@ func (wm *OrgLabelPolicyWriteModel) NewChangedEvent(
|
|||||||
if wm.SecondaryColor != secondaryColor {
|
if wm.SecondaryColor != secondaryColor {
|
||||||
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
||||||
}
|
}
|
||||||
|
if wm.HideLoginNameSuffix != hideLoginNameSuffix {
|
||||||
|
changes = append(changes, policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix))
|
||||||
|
}
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
|||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -91,8 +92,9 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
|||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
orgID: "org1",
|
orgID: "org1",
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -112,6 +114,7 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
|||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -122,8 +125,9 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
|||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
orgID: "org1",
|
orgID: "org1",
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -132,8 +136,9 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
|||||||
AggregateID: "org1",
|
AggregateID: "org1",
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
},
|
},
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -244,6 +249,7 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
|||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -253,8 +259,9 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
|||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
orgID: "org1",
|
orgID: "org1",
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color",
|
PrimaryColor: "primary-color",
|
||||||
SecondaryColor: "secondary-color",
|
SecondaryColor: "secondary-color",
|
||||||
|
HideLoginNameSuffix: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -272,13 +279,14 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
|||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
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(),
|
ctx: context.Background(),
|
||||||
orgID: "org1",
|
orgID: "org1",
|
||||||
policy: &domain.LabelPolicy{
|
policy: &domain.LabelPolicy{
|
||||||
PrimaryColor: "primary-color-change",
|
PrimaryColor: "primary-color-change",
|
||||||
SecondaryColor: "secondary-color-change",
|
SecondaryColor: "secondary-color-change",
|
||||||
|
HideLoginNameSuffix: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -298,8 +307,9 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
|||||||
AggregateID: "org1",
|
AggregateID: "org1",
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
},
|
},
|
||||||
PrimaryColor: "primary-color-change",
|
PrimaryColor: "primary-color-change",
|
||||||
SecondaryColor: "secondary-color-change",
|
SecondaryColor: "secondary-color-change",
|
||||||
|
HideLoginNameSuffix: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -381,6 +391,7 @@ func TestCommandSide_RemoveLabelPolicy(t *testing.T) {
|
|||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
"primary-color",
|
"primary-color",
|
||||||
"secondary-color",
|
"secondary-color",
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -406,7 +417,7 @@ func TestCommandSide_RemoveLabelPolicy(t *testing.T) {
|
|||||||
r := &Commands{
|
r := &Commands{
|
||||||
eventstore: tt.fields.eventstore,
|
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 {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
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,
|
event, _ := org.NewLabelPolicyChangedEvent(ctx,
|
||||||
&org.NewAggregate(orgID, orgID).Aggregate,
|
&org.NewAggregate(orgID, orgID).Aggregate,
|
||||||
[]policy.LabelPolicyChanges{
|
[]policy.LabelPolicyChanges{
|
||||||
policy.ChangePrimaryColor(primaryColor),
|
policy.ChangePrimaryColor(primaryColor),
|
||||||
policy.ChangeSecondaryColor(secondaryColor),
|
policy.ChangeSecondaryColor(secondaryColor),
|
||||||
|
policy.ChangeHideLoginNameSuffix(hideLoginNameSuffix),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return event
|
return event
|
||||||
|
@ -9,8 +9,9 @@ import (
|
|||||||
type LabelPolicyWriteModel struct {
|
type LabelPolicyWriteModel struct {
|
||||||
eventstore.WriteModel
|
eventstore.WriteModel
|
||||||
|
|
||||||
PrimaryColor string
|
PrimaryColor string
|
||||||
SecondaryColor string
|
SecondaryColor string
|
||||||
|
HideLoginNameSuffix bool
|
||||||
|
|
||||||
State domain.PolicyState
|
State domain.PolicyState
|
||||||
}
|
}
|
||||||
@ -21,6 +22,7 @@ func (wm *LabelPolicyWriteModel) Reduce() error {
|
|||||||
case *policy.LabelPolicyAddedEvent:
|
case *policy.LabelPolicyAddedEvent:
|
||||||
wm.PrimaryColor = e.PrimaryColor
|
wm.PrimaryColor = e.PrimaryColor
|
||||||
wm.SecondaryColor = e.SecondaryColor
|
wm.SecondaryColor = e.SecondaryColor
|
||||||
|
wm.HideLoginNameSuffix = e.HideLoginNameSuffix
|
||||||
wm.State = domain.PolicyStateActive
|
wm.State = domain.PolicyStateActive
|
||||||
case *policy.LabelPolicyChangedEvent:
|
case *policy.LabelPolicyChangedEvent:
|
||||||
if e.PrimaryColor != nil {
|
if e.PrimaryColor != nil {
|
||||||
@ -29,6 +31,9 @@ func (wm *LabelPolicyWriteModel) Reduce() error {
|
|||||||
if e.SecondaryColor != nil {
|
if e.SecondaryColor != nil {
|
||||||
wm.SecondaryColor = *e.SecondaryColor
|
wm.SecondaryColor = *e.SecondaryColor
|
||||||
}
|
}
|
||||||
|
if e.HideLoginNameSuffix != nil {
|
||||||
|
wm.HideLoginNameSuffix = *e.HideLoginNameSuffix
|
||||||
|
}
|
||||||
case *policy.LabelPolicyRemovedEvent:
|
case *policy.LabelPolicyRemovedEvent:
|
||||||
wm.State = domain.PolicyStateRemoved
|
wm.State = domain.PolicyStateRemoved
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,46 @@ func (c *Commands) AddHuman(ctx context.Context, orgID string, human *domain.Hum
|
|||||||
return writeModelToHuman(addedHuman), nil
|
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) {
|
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() {
|
if orgID == "" || !human.IsValid() {
|
||||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
|
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 {
|
if err != nil {
|
||||||
return nil, nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.Org.PasswordComplexity.NotFound")
|
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)
|
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.AggregateID = userID
|
||||||
human.SetNamesAsDisplayname()
|
human.SetNamesAsDisplayname()
|
||||||
if err := human.HashPasswordIfExisting(pwPolicy, c.userPasswordAlg, !selfregister); err != nil {
|
if human.Password != nil {
|
||||||
return nil, nil, err
|
if err := human.HashPasswordIfExisting(pwPolicy, c.userPasswordAlg, human.ChangeRequired); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addedHuman := NewHumanWriteModel(human.AggregateID, orgID)
|
addedHuman := NewHumanWriteModel(human.AggregateID, orgID)
|
||||||
//TODO: adlerhurst maybe we could simplify the code below
|
//TODO: adlerhurst maybe we could simplify the code below
|
||||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||||
|
@ -171,51 +171,6 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
|||||||
err: caos_errs.IsErrorInvalidArgument,
|
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",
|
name: "add human (with initial code), ok",
|
||||||
fields: fields{
|
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) {
|
func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
@ -836,54 +1338,6 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
|||||||
err: caos_errs.IsPreconditionFailed,
|
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",
|
name: "add human (with password and initial code), ok",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/errors"
|
|
||||||
"golang.org/x/text/language"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthRequest struct {
|
type AuthRequest struct {
|
||||||
@ -23,23 +25,26 @@ type AuthRequest struct {
|
|||||||
MaxAuthAge uint32
|
MaxAuthAge uint32
|
||||||
Request Request
|
Request Request
|
||||||
|
|
||||||
levelOfAssurance LevelOfAssurance
|
levelOfAssurance LevelOfAssurance
|
||||||
UserID string
|
UserID string
|
||||||
LoginName string
|
UserName string
|
||||||
DisplayName string
|
LoginName string
|
||||||
UserOrgID string
|
DisplayName string
|
||||||
RequestedOrgID string
|
UserOrgID string
|
||||||
RequestedOrgName string
|
RequestedOrgID string
|
||||||
SelectedIDPConfigID string
|
RequestedOrgName string
|
||||||
LinkingUsers []*ExternalUser
|
RequestedPrimaryDomain string
|
||||||
PossibleSteps []NextStep
|
SelectedIDPConfigID string
|
||||||
PasswordVerified bool
|
LinkingUsers []*ExternalUser
|
||||||
MFAsVerified []MFAType
|
PossibleSteps []NextStep
|
||||||
Audience []string
|
PasswordVerified bool
|
||||||
AuthTime time.Time
|
MFAsVerified []MFAType
|
||||||
Code string
|
Audience []string
|
||||||
LoginPolicy *LoginPolicy
|
AuthTime time.Time
|
||||||
AllowedExternalIDPs []*IDPProvider
|
Code string
|
||||||
|
LoginPolicy *LoginPolicy
|
||||||
|
AllowedExternalIDPs []*IDPProvider
|
||||||
|
LabelPolicy *LabelPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExternalUser struct {
|
type ExternalUser struct {
|
||||||
@ -103,8 +108,9 @@ func (a *AuthRequest) WithCurrentInfo(info *BrowserInfo) *AuthRequest {
|
|||||||
return a
|
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.UserID = userID
|
||||||
|
a.UserName = userName
|
||||||
a.LoginName = loginName
|
a.LoginName = loginName
|
||||||
a.DisplayName = displayName
|
a.DisplayName = displayName
|
||||||
a.UserOrgID = userOrgID
|
a.UserOrgID = userOrgID
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
caos_errors "github.com/caos/zitadel/internal/errors"
|
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Human struct {
|
type Human struct {
|
||||||
@ -59,9 +59,6 @@ func (u *Human) CheckOrgIAMPolicy(policy *OrgIAMPolicy) error {
|
|||||||
if policy == nil {
|
if policy == nil {
|
||||||
return caos_errors.ThrowPreconditionFailed(nil, "DOMAIN-zSH7j", "Errors.Users.OrgIamPolicyNil")
|
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 {
|
if !policy.UserLoginMustBeDomain && u.Profile != nil && u.Username == "" && u.Email != nil {
|
||||||
u.Username = u.EmailAddress
|
u.Username = u.EmailAddress
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ func (s *SelectUserStep) Type() NextStepType {
|
|||||||
|
|
||||||
type UserSelection struct {
|
type UserSelection struct {
|
||||||
UserID string
|
UserID string
|
||||||
|
UserName string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
LoginName string
|
LoginName string
|
||||||
UserSessionState UserSessionState
|
UserSessionState UserSessionState
|
||||||
|
@ -7,9 +7,10 @@ import (
|
|||||||
type LabelPolicy struct {
|
type LabelPolicy struct {
|
||||||
models.ObjectRoot
|
models.ObjectRoot
|
||||||
|
|
||||||
Default bool
|
Default bool
|
||||||
PrimaryColor string
|
PrimaryColor string
|
||||||
SecondaryColor string
|
SecondaryColor string
|
||||||
|
HideLoginNameSuffix bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *LabelPolicy) IsValid() bool {
|
func (p *LabelPolicy) IsValid() bool {
|
||||||
|
@ -7,10 +7,11 @@ import (
|
|||||||
type LabelPolicy struct {
|
type LabelPolicy struct {
|
||||||
models.ObjectRoot
|
models.ObjectRoot
|
||||||
|
|
||||||
State PolicyState
|
State PolicyState
|
||||||
Default bool
|
Default bool
|
||||||
PrimaryColor string
|
PrimaryColor string
|
||||||
SecondaryColor string
|
SecondaryColor string
|
||||||
|
HideLoginNameSuffix bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *LabelPolicy) IsValid() bool {
|
func (p *LabelPolicy) IsValid() bool {
|
||||||
|
@ -6,10 +6,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type LabelPolicyView struct {
|
type LabelPolicyView struct {
|
||||||
AggregateID string
|
AggregateID string
|
||||||
PrimaryColor string
|
PrimaryColor string
|
||||||
SecondaryColor string
|
SecondaryColor string
|
||||||
Default bool
|
HideLoginNameSuffix bool
|
||||||
|
Default bool
|
||||||
|
|
||||||
CreationDate time.Time
|
CreationDate time.Time
|
||||||
ChangeDate time.Time
|
ChangeDate time.Time
|
||||||
|
@ -10,26 +10,29 @@ import (
|
|||||||
|
|
||||||
type LabelPolicy struct {
|
type LabelPolicy struct {
|
||||||
es_models.ObjectRoot
|
es_models.ObjectRoot
|
||||||
State int32 `json:"-"`
|
State int32 `json:"-"`
|
||||||
PrimaryColor string `json:"primaryColor"`
|
PrimaryColor string `json:"primaryColor"`
|
||||||
SecondaryColor string `json:"secondaryColor"`
|
SecondaryColor string `json:"secondaryColor"`
|
||||||
|
HideLoginNameSuffix bool `json:"hideLoginNameSuffix"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LabelPolicyToModel(policy *LabelPolicy) *iam_model.LabelPolicy {
|
func LabelPolicyToModel(policy *LabelPolicy) *iam_model.LabelPolicy {
|
||||||
return &iam_model.LabelPolicy{
|
return &iam_model.LabelPolicy{
|
||||||
ObjectRoot: policy.ObjectRoot,
|
ObjectRoot: policy.ObjectRoot,
|
||||||
State: iam_model.PolicyState(policy.State),
|
State: iam_model.PolicyState(policy.State),
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
SecondaryColor: policy.SecondaryColor,
|
||||||
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LabelPolicyFromModel(policy *iam_model.LabelPolicy) *LabelPolicy {
|
func LabelPolicyFromModel(policy *iam_model.LabelPolicy) *LabelPolicy {
|
||||||
return &LabelPolicy{
|
return &LabelPolicy{
|
||||||
ObjectRoot: policy.ObjectRoot,
|
ObjectRoot: policy.ObjectRoot,
|
||||||
State: int32(policy.State),
|
State: int32(policy.State),
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
SecondaryColor: policy.SecondaryColor,
|
||||||
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||||
|
|
||||||
es_model "github.com/caos/zitadel/internal/iam/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"`
|
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||||
State int32 `json:"-" gorm:"column:label_policy_state"`
|
State int32 `json:"-" gorm:"column:label_policy_state"`
|
||||||
|
|
||||||
PrimaryColor string `json:"primaryColor" gorm:"column:primary_color"`
|
PrimaryColor string `json:"primaryColor" gorm:"column:primary_color"`
|
||||||
SecondaryColor string `json:"secondaryColor" gorm:"column:secondary_color"`
|
SecondaryColor string `json:"secondaryColor" gorm:"column:secondary_color"`
|
||||||
Default bool `json:"-" gorm:"-"`
|
HideLoginNameSuffix bool `json:"hideLoginNameSuffix" gorm:"column:hide_login_name_suffix"`
|
||||||
|
Default bool `json:"-" gorm:"-"`
|
||||||
|
|
||||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LabelPolicyViewFromModel(policy *model.LabelPolicyView) *LabelPolicyView {
|
func (p *LabelPolicyView) ToDomain() *domain.LabelPolicy {
|
||||||
return &LabelPolicyView{
|
return &domain.LabelPolicy{
|
||||||
AggregateID: policy.AggregateID,
|
ObjectRoot: models.ObjectRoot{
|
||||||
Sequence: policy.Sequence,
|
AggregateID: p.AggregateID,
|
||||||
CreationDate: policy.CreationDate,
|
CreationDate: p.CreationDate,
|
||||||
ChangeDate: policy.ChangeDate,
|
ChangeDate: p.ChangeDate,
|
||||||
PrimaryColor: policy.PrimaryColor,
|
Sequence: p.Sequence,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
},
|
||||||
Default: policy.Default,
|
Default: p.Default,
|
||||||
|
PrimaryColor: p.PrimaryColor,
|
||||||
|
SecondaryColor: p.SecondaryColor,
|
||||||
|
HideLoginNameSuffix: p.HideLoginNameSuffix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LabelPolicyViewToModel(policy *LabelPolicyView) *model.LabelPolicyView {
|
func LabelPolicyViewToModel(policy *LabelPolicyView) *model.LabelPolicyView {
|
||||||
return &model.LabelPolicyView{
|
return &model.LabelPolicyView{
|
||||||
AggregateID: policy.AggregateID,
|
AggregateID: policy.AggregateID,
|
||||||
Sequence: policy.Sequence,
|
Sequence: policy.Sequence,
|
||||||
CreationDate: policy.CreationDate,
|
CreationDate: policy.CreationDate,
|
||||||
ChangeDate: policy.ChangeDate,
|
ChangeDate: policy.ChangeDate,
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
SecondaryColor: policy.SecondaryColor,
|
||||||
Default: policy.Default,
|
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
|
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) {
|
func (repo *OrgRepository) GetLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
|
||||||
policy, viewErr := repo.View.LoginPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
policy, viewErr := repo.View.LoginPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||||
if viewErr != nil && !errors.IsNotFound(viewErr) {
|
if viewErr != nil && !errors.IsNotFound(viewErr) {
|
||||||
|
@ -45,4 +45,7 @@ type OrgRepository interface {
|
|||||||
|
|
||||||
GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
||||||
GetMailTexts(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,
|
aggregate *eventstore.Aggregate,
|
||||||
primaryColor,
|
primaryColor,
|
||||||
secondaryColor string,
|
secondaryColor string,
|
||||||
|
hideLoginNameSuffix bool,
|
||||||
) *LabelPolicyAddedEvent {
|
) *LabelPolicyAddedEvent {
|
||||||
return &LabelPolicyAddedEvent{
|
return &LabelPolicyAddedEvent{
|
||||||
LabelPolicyAddedEvent: *policy.NewLabelPolicyAddedEvent(
|
LabelPolicyAddedEvent: *policy.NewLabelPolicyAddedEvent(
|
||||||
@ -30,7 +31,8 @@ func NewLabelPolicyAddedEvent(
|
|||||||
aggregate,
|
aggregate,
|
||||||
LabelPolicyAddedEventType),
|
LabelPolicyAddedEventType),
|
||||||
primaryColor,
|
primaryColor,
|
||||||
secondaryColor),
|
secondaryColor,
|
||||||
|
hideLoginNameSuffix),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ func NewLabelPolicyAddedEvent(
|
|||||||
aggregate *eventstore.Aggregate,
|
aggregate *eventstore.Aggregate,
|
||||||
primaryColor,
|
primaryColor,
|
||||||
secondaryColor string,
|
secondaryColor string,
|
||||||
|
hideLoginNameSuffix bool,
|
||||||
) *LabelPolicyAddedEvent {
|
) *LabelPolicyAddedEvent {
|
||||||
return &LabelPolicyAddedEvent{
|
return &LabelPolicyAddedEvent{
|
||||||
LabelPolicyAddedEvent: *policy.NewLabelPolicyAddedEvent(
|
LabelPolicyAddedEvent: *policy.NewLabelPolicyAddedEvent(
|
||||||
@ -31,7 +32,8 @@ func NewLabelPolicyAddedEvent(
|
|||||||
aggregate,
|
aggregate,
|
||||||
LabelPolicyAddedEventType),
|
LabelPolicyAddedEventType),
|
||||||
primaryColor,
|
primaryColor,
|
||||||
secondaryColor),
|
secondaryColor,
|
||||||
|
hideLoginNameSuffix),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,9 @@ const (
|
|||||||
type LabelPolicyAddedEvent struct {
|
type LabelPolicyAddedEvent struct {
|
||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
PrimaryColor string `json:"primaryColor,omitempty"`
|
PrimaryColor string `json:"primaryColor,omitempty"`
|
||||||
SecondaryColor string `json:"secondaryColor,omitempty"`
|
SecondaryColor string `json:"secondaryColor,omitempty"`
|
||||||
|
HideLoginNameSuffix bool `json:"hideLoginNameSuffix,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *LabelPolicyAddedEvent) Data() interface{} {
|
func (e *LabelPolicyAddedEvent) Data() interface{} {
|
||||||
@ -32,12 +33,14 @@ func NewLabelPolicyAddedEvent(
|
|||||||
base *eventstore.BaseEvent,
|
base *eventstore.BaseEvent,
|
||||||
primaryColor,
|
primaryColor,
|
||||||
secondaryColor string,
|
secondaryColor string,
|
||||||
|
hideLoginNameSuffix bool,
|
||||||
) *LabelPolicyAddedEvent {
|
) *LabelPolicyAddedEvent {
|
||||||
|
|
||||||
return &LabelPolicyAddedEvent{
|
return &LabelPolicyAddedEvent{
|
||||||
BaseEvent: *base,
|
BaseEvent: *base,
|
||||||
PrimaryColor: primaryColor,
|
PrimaryColor: primaryColor,
|
||||||
SecondaryColor: secondaryColor,
|
SecondaryColor: secondaryColor,
|
||||||
|
HideLoginNameSuffix: hideLoginNameSuffix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,8 +60,9 @@ func LabelPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReade
|
|||||||
type LabelPolicyChangedEvent struct {
|
type LabelPolicyChangedEvent struct {
|
||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
PrimaryColor *string `json:"primaryColor,omitempty"`
|
PrimaryColor *string `json:"primaryColor,omitempty"`
|
||||||
SecondaryColor *string `json:"secondaryColor,omitempty"`
|
SecondaryColor *string `json:"secondaryColor,omitempty"`
|
||||||
|
HideLoginNameSuffix *bool `json:"hideLoginNameSuffix,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *LabelPolicyChangedEvent) Data() interface{} {
|
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) {
|
func LabelPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
e := &LabelPolicyChangedEvent{
|
e := &LabelPolicyChangedEvent{
|
||||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
@ -54,7 +54,8 @@ func (l *Login) handleLoginNameCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
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 {
|
if err != nil {
|
||||||
l.renderLogin(w, r, authReq, err)
|
l.renderLogin(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@ -73,7 +74,7 @@ func (l *Login) renderLogin(w http.ResponseWriter, r *http.Request, authReq *dom
|
|||||||
return authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowUsernamePassword
|
return authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowUsernamePassword
|
||||||
},
|
},
|
||||||
"hasExternalLogin": func() bool {
|
"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)
|
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,
|
ErrType: errType,
|
||||||
ErrMessage: errMessage,
|
ErrMessage: errMessage,
|
||||||
},
|
},
|
||||||
Lang: l.renderer.Lang(r).String(),
|
Lang: l.renderer.Lang(r).String(),
|
||||||
Title: title,
|
Title: title,
|
||||||
Theme: l.getTheme(r),
|
Theme: l.getTheme(r),
|
||||||
ThemeMode: l.getThemeMode(r),
|
ThemeMode: l.getThemeMode(r),
|
||||||
OrgID: l.getOrgID(authReq),
|
OrgID: l.getOrgID(authReq),
|
||||||
OrgName: l.getOrgName(authReq),
|
OrgName: l.getOrgName(authReq),
|
||||||
AuthReqID: getRequestID(authReq, r),
|
PrimaryDomain: l.getOrgPrimaryDomain(authReq),
|
||||||
CSRF: csrf.TemplateField(r),
|
DisplayLoginNameSuffix: l.isDisplayLoginNameSuffix(authReq),
|
||||||
Nonce: http_mw.GetNonce(r),
|
AuthReqID: getRequestID(authReq, r),
|
||||||
|
CSRF: csrf.TemplateField(r),
|
||||||
|
Nonce: http_mw.GetNonce(r),
|
||||||
}
|
}
|
||||||
if authReq != nil {
|
if authReq != nil {
|
||||||
baseData.LoginPolicy = authReq.LoginPolicy
|
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 {
|
func (l *Login) getProfileData(authReq *domain.AuthRequest) profileData {
|
||||||
var loginName, displayName string
|
var userName, loginName, displayName string
|
||||||
if authReq != nil {
|
if authReq != nil {
|
||||||
|
userName = authReq.UserName
|
||||||
loginName = authReq.LoginName
|
loginName = authReq.LoginName
|
||||||
displayName = authReq.DisplayName
|
displayName = authReq.DisplayName
|
||||||
}
|
}
|
||||||
return profileData{
|
return profileData{
|
||||||
|
UserName: userName,
|
||||||
LoginName: loginName,
|
LoginName: loginName,
|
||||||
DisplayName: displayName,
|
DisplayName: displayName,
|
||||||
}
|
}
|
||||||
@ -329,6 +333,23 @@ func (l *Login) getOrgName(authReq *domain.AuthRequest) string {
|
|||||||
return authReq.RequestedOrgName
|
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 {
|
func getRequestID(authReq *domain.AuthRequest, r *http.Request) string {
|
||||||
if authReq != nil {
|
if authReq != nil {
|
||||||
return authReq.ID
|
return authReq.ID
|
||||||
@ -351,17 +372,19 @@ func (l *Login) cspErrorHandler(err error) http.Handler {
|
|||||||
|
|
||||||
type baseData struct {
|
type baseData struct {
|
||||||
errorData
|
errorData
|
||||||
Lang string
|
Lang string
|
||||||
Title string
|
Title string
|
||||||
Theme string
|
Theme string
|
||||||
ThemeMode string
|
ThemeMode string
|
||||||
OrgID string
|
OrgID string
|
||||||
OrgName string
|
OrgName string
|
||||||
AuthReqID string
|
PrimaryDomain string
|
||||||
CSRF template.HTML
|
DisplayLoginNameSuffix bool
|
||||||
Nonce string
|
AuthReqID string
|
||||||
LoginPolicy *domain.LoginPolicy
|
CSRF template.HTML
|
||||||
IDPProviders []*domain.IDPProvider
|
Nonce string
|
||||||
|
LoginPolicy *domain.LoginPolicy
|
||||||
|
IDPProviders []*domain.IDPProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
type errorData struct {
|
type errorData struct {
|
||||||
@ -380,6 +403,7 @@ type userData struct {
|
|||||||
|
|
||||||
type profileData struct {
|
type profileData struct {
|
||||||
LoginName string
|
LoginName string
|
||||||
|
UserName string
|
||||||
DisplayName 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:
|
Login:
|
||||||
Title: Anmeldung
|
Title: Anmeldung
|
||||||
Description: Mit ZITADEL-Konto anmelden.
|
Description: Mit ZITADEL-Konto anmelden.
|
||||||
TitleLinking: Anmeldung für Benutzer Linking
|
TitleLinking: Anmeldung für Benutzer Linking
|
||||||
DescriptionLinking: Gib deine Benutzerdaten ein um den externen Benutzer mit einem ZITADEL Benutzer zu linken.
|
DescriptionLinking: Gib deine Benutzerdaten ein um den externen Benutzer mit einem ZITADEL Benutzer zu linken.
|
||||||
Loginname: Loginname
|
Loginname: Loginname
|
||||||
|
UsernamePlaceHolder: username
|
||||||
LoginnamePlaceHolder: username@domain
|
LoginnamePlaceHolder: username@domain
|
||||||
ExternalLogin: Melde dich mit einem externen Benutzer an
|
ExternalLogin: Melde dich mit einem externen Benutzer an
|
||||||
MustBeMemberOfOrg: Der Benutzer muss der Organisation {{.OrgName}} angehören.
|
MustBeMemberOfOrg: Der Benutzer muss der Organisation {{.OrgName}} angehören.
|
||||||
@ -28,6 +19,16 @@ UserSelection:
|
|||||||
SessionState1: inaktiv
|
SessionState1: inaktiv
|
||||||
MustBeMemberOfOrg: Der Benutzer muss der Organisation {{.OrgName}} angehören.
|
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:
|
UsernameChange:
|
||||||
Title: Usernamen ändern
|
Title: Usernamen ändern
|
||||||
Description: Wähle deinen neuen Benutzernamen
|
Description: Wähle deinen neuen Benutzernamen
|
||||||
|
@ -4,9 +4,10 @@ Login:
|
|||||||
TitleLinking: Login for userlinking
|
TitleLinking: Login for userlinking
|
||||||
DescriptionLinking: Enter your login data to link your external user with a ZITADEL user.
|
DescriptionLinking: Enter your login data to link your external user with a ZITADEL user.
|
||||||
Loginname: Loginname
|
Loginname: Loginname
|
||||||
|
UsernamePlaceHolder: username
|
||||||
LoginnamePlaceHolder: username@domain
|
LoginnamePlaceHolder: username@domain
|
||||||
ExternalLogin: Login with an external user.
|
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:
|
UserSelection:
|
||||||
Title: Select account
|
Title: Select account
|
||||||
@ -16,7 +17,7 @@ UserSelection:
|
|||||||
OtherUser: Other User
|
OtherUser: Other User
|
||||||
SessionState0: active
|
SessionState0: active
|
||||||
SessionState1: inactive
|
SessionState1: inactive
|
||||||
MustBeMemberOfOrg: The user must be mermber of the {{.OrgDomain}} organisation.
|
MustBeMemberOfOrg: The user must be mermber of the {{.OrgName}} organisation.
|
||||||
|
|
||||||
Password:
|
Password:
|
||||||
Title: Password
|
Title: Password
|
||||||
|
@ -12,6 +12,11 @@ $lgn-container-margin: 0px auto 50px auto;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
padding: .5rem 1rem;
|
padding: .5rem 1rem;
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
box-shadow: inset 0 -1px lgn-color($foreground, footer-line);
|
box-shadow: inset 0 -1px lgn-color($foreground, footer-line);
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
$primary: map-get($config, primary);
|
$primary: map-get($config, primary);
|
||||||
|
@ -440,6 +440,10 @@ i {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.lgn-account-selection .lgn-account:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.lgn-account-selection .lgn-account .left {
|
.lgn-account-selection .lgn-account .left {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
@ -1298,6 +1302,10 @@ i {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.lgn-account-selection .lgn-account:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.lgn-account-selection .lgn-account .left {
|
.lgn-account-selection .lgn-account .left {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -440,6 +440,10 @@ i {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.lgn-account-selection .lgn-account:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.lgn-account-selection .lgn-account .left {
|
.lgn-account-selection .lgn-account .left {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
@ -1202,7 +1206,6 @@ a:hover, a:active {
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
box-shadow: inset 0 -1px #303131;
|
box-shadow: inset 0 -1px #303131;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
.lgn-account-selection .lgn-account:hover {
|
.lgn-account-selection .lgn-account:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.02);
|
background-color: rgba(255, 255, 255, 0.02);
|
||||||
@ -1522,7 +1525,6 @@ a:hover, a:active {
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
box-shadow: inset 0 -1px #303131;
|
box-shadow: inset 0 -1px #303131;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
.lgn-dark-theme .lgn-account-selection .lgn-account:hover {
|
.lgn-dark-theme .lgn-account-selection .lgn-account:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.02);
|
background-color: rgba(255, 255, 255, 0.02);
|
||||||
@ -1836,7 +1838,6 @@ a:hover, a:active {
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
box-shadow: inset 0 -1px #e3e8ee;
|
box-shadow: inset 0 -1px #e3e8ee;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
.lgn-light-theme .lgn-account-selection .lgn-account:hover {
|
.lgn-light-theme .lgn-account-selection .lgn-account:hover {
|
||||||
background-color: rgba(0, 0, 0, 0.02);
|
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 }}
|
{{if hasUsernamePasswordLogin }}
|
||||||
<div class="fields">
|
<div class="fields">
|
||||||
<label class="lgn-label" for="loginName">{{t "Login.Loginname"}}</label>
|
<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"}}"
|
<div class="lgn-suffix-wrapper">
|
||||||
value="{{ .LoginName }}" {{if .ErrMessage}}shake {{end}} autocomplete="username" autofocus required>
|
<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>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
@ -53,5 +58,6 @@
|
|||||||
|
|
||||||
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
|
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
|
||||||
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
|
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
|
||||||
|
<script src="{{ resourceUrl "scripts/input_suffix_offset.js" }}"></script>
|
||||||
|
|
||||||
{{template "main-bottom" .}}
|
{{template "main-bottom" .}}
|
@ -23,10 +23,11 @@
|
|||||||
|
|
||||||
<div class="lgn-account-selection">
|
<div class="lgn-account-selection">
|
||||||
{{ if .Users }}
|
{{ if .Users }}
|
||||||
|
{{ $displayLoginNameSuffix := and .OrgID (not .DisplayLoginNameSuffix)}}
|
||||||
{{ range $user := .Users }}
|
{{ range $user := .Users }}
|
||||||
{{ $sessionState := (printf "UserSelection.SessionState%v" $user.UserSessionState) }}
|
{{ $sessionState := (printf "UserSelection.SessionState%v" $user.UserSessionState) }}
|
||||||
<button type="submit" name="userID" value="{{$user.UserID}}" class="lgn-account"
|
<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="left">
|
||||||
<div class="lgn-avatar" displayname="{{$user.DisplayName}}">
|
<div class="lgn-avatar" displayname="{{$user.DisplayName}}">
|
||||||
<span class="initials">A</span>
|
<span class="initials">A</span>
|
||||||
@ -34,7 +35,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="lgn-names">
|
<div class="lgn-names">
|
||||||
<p class="lgn-displayname">{{$user.DisplayName}}</p>
|
<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>
|
<p class="lgn-session-state i{{$user.UserSessionState}}">{{t $sessionState}}</p>
|
||||||
</div>
|
</div>
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{{define "user-profile"}}
|
{{define "user-profile"}}
|
||||||
{{if .LoginName}}
|
{{if or .LoginName .UserName}}
|
||||||
<div class="lgn-login-profile">
|
<div class="lgn-login-profile">
|
||||||
<div class="lgn-profile-image"></div>
|
<div class="lgn-profile-image"></div>
|
||||||
<div class="lgn-names">
|
<div class="lgn-names">
|
||||||
@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="lgn-loginname">
|
<div class="lgn-loginname">
|
||||||
<p>{{.LoginName}}</p>
|
<p>{{if .DisplayLoginNameSuffix}}{{.LoginName}}{{else}}{{.UserName}}{{end}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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 {
|
message UpdateLabelPolicyRequest {
|
||||||
string primary_color = 1 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
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}];
|
string secondary_color = 2 [(validate.rules).string = {min_len: 1, max_len: 50}];
|
||||||
|
bool hide_login_name_suffix = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UpdateLabelPolicyResponse {
|
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) {
|
rpc AddMachineUser(AddMachineUserRequest) returns (AddMachineUserResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
post: "/users/machine"
|
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) {
|
rpc GetOrgIDPByID(GetOrgIDPByIDRequest) returns (GetOrgIDPByIDResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
get: "/idps/{id}"
|
get: "/idps/{id}"
|
||||||
@ -1825,6 +1888,39 @@ message AddHumanUserResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 2;
|
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 {
|
message AddMachineUserRequest {
|
||||||
string user_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
string user_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
|
||||||
@ -3097,6 +3193,45 @@ message ResetPasswordLockoutPolicyToDefaultResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 1;
|
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 {
|
message GetOrgIDPByIDRequest {
|
||||||
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ message LabelPolicy {
|
|||||||
string primary_color = 2;
|
string primary_color = 2;
|
||||||
string secondary_color = 3;
|
string secondary_color = 3;
|
||||||
bool is_default = 4;
|
bool is_default = 4;
|
||||||
|
bool hide_login_name_suffix = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LoginPolicy {
|
message LoginPolicy {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user