mirror of
https://github.com/zitadel/zitadel.git
synced 2025-05-22 15:48:19 +00:00
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>
This commit is contained in:
parent
a012aed5cb
commit
03ddb8fc38
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
admin_model "github.com/caos/zitadel/internal/admin/model"
|
admin_model "github.com/caos/zitadel/internal/admin/model"
|
||||||
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
@ -58,7 +59,7 @@ func (repo *OrgRepo) SetUpOrg(ctx context.Context, setUp *admin_model.SetupOrg)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
user, userAggregates, err := repo.UserEventstore.PrepareCreateUser(ctx, setUp.User, pwPolicyView, orgPolicy, org.AggregateID)
|
user, userAggregates, err := repo.UserEventstore.PrepareCreateUser(ctx, setUp.User, pwPolicyView, orgPolicy, true, org.AggregateID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,9 @@ import (
|
|||||||
|
|
||||||
func labelPolicyToModel(policy *admin.DefaultLabelPolicyUpdate) *iam_model.LabelPolicy {
|
func labelPolicyToModel(policy *admin.DefaultLabelPolicyUpdate) *iam_model.LabelPolicy {
|
||||||
return &iam_model.LabelPolicy{
|
return &iam_model.LabelPolicy{
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
SecondaryColor: policy.SecondaryColor,
|
||||||
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,10 +23,11 @@ func labelPolicyFromModel(policy *iam_model.LabelPolicy) *admin.DefaultLabelPoli
|
|||||||
logging.Log("ADMIN-mAgcI").OnError(err).Debug("date parse failed")
|
logging.Log("ADMIN-mAgcI").OnError(err).Debug("date parse failed")
|
||||||
|
|
||||||
return &admin.DefaultLabelPolicy{
|
return &admin.DefaultLabelPolicy{
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
SecondaryColor: policy.SecondaryColor,
|
||||||
CreationDate: creationDate,
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
ChangeDate: changeDate,
|
CreationDate: creationDate,
|
||||||
|
ChangeDate: changeDate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +39,10 @@ func labelPolicyViewFromModel(policy *iam_model.LabelPolicyView) *admin.DefaultL
|
|||||||
logging.Log("ADMIN-Vhvfp").OnError(err).Debug("date parse failed")
|
logging.Log("ADMIN-Vhvfp").OnError(err).Debug("date parse failed")
|
||||||
|
|
||||||
return &admin.DefaultLabelPolicyView{
|
return &admin.DefaultLabelPolicyView{
|
||||||
PrimaryColor: policy.PrimaryColor,
|
PrimaryColor: policy.PrimaryColor,
|
||||||
SecondaryColor: policy.SecondaryColor,
|
SecondaryColor: policy.SecondaryColor,
|
||||||
CreationDate: creationDate,
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
ChangeDate: changeDate,
|
CreationDate: creationDate,
|
||||||
|
ChangeDate: changeDate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
internal/api/grpc/management/label_policy.go
Normal file
45
internal/api/grpc/management/label_policy.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package management
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/pkg/grpc/management"
|
||||||
|
"github.com/golang/protobuf/ptypes/empty"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) GetLabelPolicy(ctx context.Context, _ *empty.Empty) (*management.LabelPolicyView, error) {
|
||||||
|
result, err := s.org.GetLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return labelPolicyViewFromModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetDefaultLabelPolicy(ctx context.Context, _ *empty.Empty) (*management.LabelPolicyView, error) {
|
||||||
|
result, err := s.org.GetLabelPolicy(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return labelPolicyViewFromModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) CreateLabelPolicy(ctx context.Context, policy *management.LabelPolicyRequest) (*management.LabelPolicy, error) {
|
||||||
|
result, err := s.org.AddLabelPolicy(ctx, labelPolicyRequestToModel(policy))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return labelPolicyFromModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) UpdateLabelPolicy(ctx context.Context, policy *management.LabelPolicyRequest) (*management.LabelPolicy, error) {
|
||||||
|
result, err := s.org.ChangeLabelPolicy(ctx, labelPolicyRequestToModel(policy))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return labelPolicyFromModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) RemoveLabelPolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) {
|
||||||
|
err := s.org.RemoveLabelPolicy(ctx)
|
||||||
|
return &empty.Empty{}, err
|
||||||
|
}
|
50
internal/api/grpc/management/label_policy_converter.go
Normal file
50
internal/api/grpc/management/label_policy_converter.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package management
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/logging"
|
||||||
|
"github.com/golang/protobuf/ptypes"
|
||||||
|
|
||||||
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
|
"github.com/caos/zitadel/pkg/grpc/management"
|
||||||
|
)
|
||||||
|
|
||||||
|
func labelPolicyRequestToModel(policy *management.LabelPolicyRequest) *iam_model.LabelPolicy {
|
||||||
|
return &iam_model.LabelPolicy{
|
||||||
|
SecondaryColor: policy.SecondaryColor,
|
||||||
|
PrimaryColor: policy.PrimaryColor,
|
||||||
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func labelPolicyFromModel(policy *iam_model.LabelPolicy) *management.LabelPolicy {
|
||||||
|
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
|
||||||
|
logging.Log("GRPC-2Fsm8").OnError(err).Debug("date parse failed")
|
||||||
|
|
||||||
|
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
|
||||||
|
logging.Log("GRPC-3Flo0").OnError(err).Debug("date parse failed")
|
||||||
|
|
||||||
|
return &management.LabelPolicy{
|
||||||
|
SecondaryColor: policy.SecondaryColor,
|
||||||
|
PrimaryColor: policy.PrimaryColor,
|
||||||
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
|
CreationDate: creationDate,
|
||||||
|
ChangeDate: changeDate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func labelPolicyViewFromModel(policy *iam_model.LabelPolicyView) *management.LabelPolicyView {
|
||||||
|
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
|
||||||
|
logging.Log("GRPC-5Tsm8").OnError(err).Debug("date parse failed")
|
||||||
|
|
||||||
|
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
|
||||||
|
logging.Log("GRPC-8dJgs").OnError(err).Debug("date parse failed")
|
||||||
|
|
||||||
|
return &management.LabelPolicyView{
|
||||||
|
Default: policy.Default,
|
||||||
|
SecondaryColor: policy.SecondaryColor,
|
||||||
|
PrimaryColor: policy.PrimaryColor,
|
||||||
|
HideLoginNameSuffix: policy.HideLoginNameSuffix,
|
||||||
|
CreationDate: creationDate,
|
||||||
|
ChangeDate: changeDate,
|
||||||
|
}
|
||||||
|
}
|
@ -59,6 +59,14 @@ func (s *Server) CreateUser(ctx context.Context, in *management.CreateUserReques
|
|||||||
return userFromModel(user), nil
|
return userFromModel(user), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) ImportHuman(ctx context.Context, in *management.ImportHumanRequest) (*management.UserResponse, error) {
|
||||||
|
user, err := s.user.ImportUser(ctx, humanImportToModel(in), in.PasswordChangeRequired)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return userFromModel(user), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) DeactivateUser(ctx context.Context, in *management.UserID) (*management.UserResponse, error) {
|
func (s *Server) DeactivateUser(ctx context.Context, in *management.UserID) (*management.UserResponse, error) {
|
||||||
user, err := s.user.DeactivateUser(ctx, in.Id)
|
user, err := s.user.DeactivateUser(ctx, in.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -60,6 +60,42 @@ func userCreateToModel(user *management.CreateUserRequest) *usr_model.User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func humanImportToModel(user *management.ImportHumanRequest) *usr_model.User {
|
||||||
|
preferredLanguage, err := language.Parse(user.PreferredLanguage)
|
||||||
|
logging.Log("GRPC-cK5k2").OnError(err).Debug("language malformed")
|
||||||
|
|
||||||
|
human := &usr_model.Human{
|
||||||
|
Profile: &usr_model.Profile{
|
||||||
|
FirstName: user.FirstName,
|
||||||
|
LastName: user.LastName,
|
||||||
|
NickName: user.NickName,
|
||||||
|
PreferredLanguage: preferredLanguage,
|
||||||
|
Gender: genderToModel(user.Gender),
|
||||||
|
},
|
||||||
|
Email: &usr_model.Email{
|
||||||
|
EmailAddress: user.Email,
|
||||||
|
IsEmailVerified: user.IsEmailVerified,
|
||||||
|
},
|
||||||
|
Address: &usr_model.Address{
|
||||||
|
Country: user.Country,
|
||||||
|
Locality: user.Locality,
|
||||||
|
PostalCode: user.PostalCode,
|
||||||
|
Region: user.Region,
|
||||||
|
StreetAddress: user.StreetAddress,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if user.Password != "" {
|
||||||
|
human.Password = &usr_model.Password{SecretString: user.Password}
|
||||||
|
}
|
||||||
|
if user.Phone != "" {
|
||||||
|
human.Phone = &usr_model.Phone{PhoneNumber: user.Phone, IsPhoneVerified: user.IsPhoneVerified}
|
||||||
|
}
|
||||||
|
return &usr_model.User{
|
||||||
|
UserName: user.UserName,
|
||||||
|
Human: human,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func passwordRequestToModel(r *management.PasswordRequest) *usr_model.Password {
|
func passwordRequestToModel(r *management.PasswordRequest) *usr_model.Password {
|
||||||
return &usr_model.Password{
|
return &usr_model.Password{
|
||||||
ObjectRoot: models.ObjectRoot{AggregateID: r.Id},
|
ObjectRoot: models.ObjectRoot{AggregateID: r.Id},
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,21 +456,30 @@ func (repo *AuthRequestRepo) fillLoginPolicy(ctx context.Context, request *model
|
|||||||
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 *model.AuthRequest, loginName string) (err error) {
|
func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *model.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 {
|
||||||
@ -484,7 +493,7 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *model.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
request.SetUserInfo(user.ID, loginName, "", user.ResourceOwner)
|
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", user.ResourceOwner)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +536,7 @@ func (repo *AuthRequestRepo) checkExternalUserLogin(request *model.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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,6 +639,7 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *model.AuthRequest) (
|
|||||||
users[i] = model.UserSelection{
|
users[i] = model.UserSelection{
|
||||||
UserID: session.UserID,
|
UserID: session.UserID,
|
||||||
DisplayName: session.DisplayName,
|
DisplayName: session.DisplayName,
|
||||||
|
UserName: session.UserName,
|
||||||
LoginName: session.LoginName,
|
LoginName: session.LoginName,
|
||||||
UserSessionState: session.State,
|
UserSessionState: session.State,
|
||||||
SelectionPossible: request.RequestedOrgID == "" || request.RequestedOrgID == session.ResourceOwner,
|
SelectionPossible: request.RequestedOrgID == "" || request.RequestedOrgID == session.ResourceOwner,
|
||||||
@ -733,6 +743,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) (*iam_model.LabelPolicyView, 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 iam_es_model.LabelPolicyViewToModel(policy), err
|
||||||
|
}
|
||||||
|
|
||||||
func setOrgID(orgViewProvider orgViewProvider, request *model.AuthRequest) error {
|
func setOrgID(orgViewProvider orgViewProvider, request *model.AuthRequest) error {
|
||||||
primaryDomain := request.GetScopeOrgPrimaryDomain()
|
primaryDomain := request.GetScopeOrgPrimaryDomain()
|
||||||
if primaryDomain == "" {
|
if primaryDomain == "" {
|
||||||
@ -745,6 +770,7 @@ func setOrgID(orgViewProvider orgViewProvider, request *model.AuthRequest) error
|
|||||||
}
|
}
|
||||||
request.RequestedOrgID = org.ID
|
request.RequestedOrgID = org.ID
|
||||||
request.RequestedOrgName = org.Name
|
request.RequestedOrgName = org.Name
|
||||||
|
request.RequestedPrimaryDomain = primaryDomain
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
|||||||
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},
|
||||||
repos.ProjectEvents),
|
repos.ProjectEvents),
|
||||||
|
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"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/models"
|
||||||
|
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/query"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/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 *eventstore.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/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
|
||||||
|
@ -50,6 +50,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
|
||||||
|
@ -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 {
|
||||||
|
@ -7,10 +7,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
|
||||||
|
@ -11,26 +11,29 @@ import (
|
|||||||
|
|
||||||
type LabelPolicy struct {
|
type LabelPolicy struct {
|
||||||
models.ObjectRoot
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,34 +24,37 @@ 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 LabelPolicyViewFromModel(policy *model.LabelPolicyView) *LabelPolicyView {
|
||||||
return &LabelPolicyView{
|
return &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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +326,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.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, 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) AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
|
func (repo *OrgRepository) AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
|
||||||
policy.AggregateID = authz.GetCtxData(ctx).OrgID
|
policy.AggregateID = authz.GetCtxData(ctx).OrgID
|
||||||
return repo.OrgEventstore.AddLabelPolicy(ctx, policy)
|
return repo.OrgEventstore.AddLabelPolicy(ctx, policy)
|
||||||
@ -336,6 +362,13 @@ func (repo *OrgRepository) ChangeLabelPolicy(ctx context.Context, policy *iam_mo
|
|||||||
return repo.OrgEventstore.ChangeLabelPolicy(ctx, policy)
|
return repo.OrgEventstore.ChangeLabelPolicy(ctx, policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *OrgRepository) RemoveLabelPolicy(ctx context.Context) error {
|
||||||
|
policy := &iam_model.LabelPolicy{ObjectRoot: models.ObjectRoot{
|
||||||
|
AggregateID: authz.GetCtxData(ctx).OrgID,
|
||||||
|
}}
|
||||||
|
return repo.OrgEventstore.RemoveLabelPolicy(ctx, policy)
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -82,6 +82,26 @@ func (repo *UserRepo) CreateUser(ctx context.Context, user *usr_model.User) (*us
|
|||||||
return repo.UserEvents.CreateUser(ctx, user, pwPolicyView, orgPolicyView)
|
return repo.UserEvents.CreateUser(ctx, user, pwPolicyView, orgPolicyView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *UserRepo) ImportUser(ctx context.Context, user *usr_model.User, passwordChangeRequired bool) (*usr_model.User, error) {
|
||||||
|
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||||
|
if err != nil && caos_errs.IsNotFound(err) {
|
||||||
|
pwPolicy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(pwPolicy)
|
||||||
|
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||||
|
if err != nil && errors.IsNotFound(err) {
|
||||||
|
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
|
||||||
|
return repo.UserEvents.ImportUser(ctx, user, pwPolicyView, orgPolicyView, passwordChangeRequired)
|
||||||
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) RegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*usr_model.User, error) {
|
func (repo *UserRepo) RegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*usr_model.User, error) {
|
||||||
policyResourceOwner := authz.GetCtxData(ctx).OrgID
|
policyResourceOwner := authz.GetCtxData(ctx).OrgID
|
||||||
if resourceOwner != "" {
|
if resourceOwner != "" {
|
||||||
|
@ -86,4 +86,10 @@ type OrgRepository interface {
|
|||||||
AddMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_model.MailText, error)
|
AddMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_model.MailText, error)
|
||||||
ChangeMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_model.MailText, error)
|
ChangeMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_model.MailText, error)
|
||||||
RemoveMailText(ctx context.Context, mailText *iam_model.MailText) error
|
RemoveMailText(ctx context.Context, mailText *iam_model.MailText) error
|
||||||
|
|
||||||
|
GetLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||||
|
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||||
|
AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
|
||||||
|
ChangeLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
|
||||||
|
RemoveLabelPolicy(ctx context.Context) error
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
type UserRepository interface {
|
type UserRepository interface {
|
||||||
UserByID(ctx context.Context, id string) (*model.UserView, error)
|
UserByID(ctx context.Context, id string) (*model.UserView, error)
|
||||||
CreateUser(ctx context.Context, user *model.User) (*model.User, error)
|
CreateUser(ctx context.Context, user *model.User) (*model.User, error)
|
||||||
|
ImportUser(ctx context.Context, user *model.User, passwordChangeRequired bool) (*model.User, error)
|
||||||
RegisterUser(ctx context.Context, user *model.User, resourceOwner string) (*model.User, error)
|
RegisterUser(ctx context.Context, user *model.User, resourceOwner string) (*model.User, error)
|
||||||
DeactivateUser(ctx context.Context, id string) (*model.User, error)
|
DeactivateUser(ctx context.Context, id string) (*model.User, error)
|
||||||
ReactivateUser(ctx context.Context, id string) (*model.User, error)
|
ReactivateUser(ctx context.Context, id string) (*model.User, error)
|
||||||
|
@ -758,6 +758,20 @@ func (es *OrgEventstore) ChangeLabelPolicy(ctx context.Context, policy *iam_mode
|
|||||||
return iam_es_model.LabelPolicyToModel(repoOrg.LabelPolicy), nil
|
return iam_es_model.LabelPolicyToModel(repoOrg.LabelPolicy), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (es *OrgEventstore) RemoveLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) error {
|
||||||
|
if policy == nil || !policy.IsValid() {
|
||||||
|
return errors.ThrowPreconditionFailed(nil, "EVENT-M9gs", "Errors.Org.LabelPolicy.Invalid")
|
||||||
|
}
|
||||||
|
org, err := es.OrgByID(ctx, org_model.NewOrg(policy.AggregateID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
repoOrg := model.OrgFromModel(org)
|
||||||
|
|
||||||
|
addAggregate := LabelPolicyRemovedAggregate(es.Eventstore.AggregateCreator(), repoOrg)
|
||||||
|
return es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||||
|
}
|
||||||
|
|
||||||
func (es *OrgEventstore) AddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
|
func (es *OrgEventstore) AddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
|
||||||
if policy == nil || !policy.IsValid() {
|
if policy == nil || !policy.IsValid() {
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-Sjkl9", "Errors.Org.LoginPolicy.Invalid")
|
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-Sjkl9", "Errors.Org.LoginPolicy.Invalid")
|
||||||
|
@ -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 *mod
|
|||||||
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 *model.AuthRequest, title s
|
|||||||
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 *model.AuthRequest, title s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) getProfileData(authReq *model.AuthRequest) profileData {
|
func (l *Login) getProfileData(authReq *model.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 *model.AuthRequest) string {
|
|||||||
return authReq.RequestedOrgName
|
return authReq.RequestedOrgName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Login) getOrgPrimaryDomain(authReq *model.AuthRequest) string {
|
||||||
|
if authReq == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return authReq.RequestedPrimaryDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Login) isDisplayLoginNameSuffix(authReq *model.AuthRequest) bool {
|
||||||
|
if authReq == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if authReq.RequestedOrgID == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return authReq.LabelPolicy != nil && !authReq.LabelPolicy.HideLoginNameSuffix
|
||||||
|
}
|
||||||
|
|
||||||
func getRequestID(authReq *model.AuthRequest, r *http.Request) string {
|
func getRequestID(authReq *model.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 *iam_model.LoginPolicyView
|
CSRF template.HTML
|
||||||
IDPProviders []*iam_model.IDPProviderView
|
Nonce string
|
||||||
|
LoginPolicy *iam_model.LoginPolicyView
|
||||||
|
IDPProviders []*iam_model.IDPProviderView
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ Login:
|
|||||||
Loginname: Loginname
|
Loginname: Loginname
|
||||||
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 +16,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>
|
||||||
|
<div class="lgn-suffix-wrapper">
|
||||||
<input class="lgn-input lgn-suffix-input" type="text" id="loginName" name="loginName" placeholder="{{t "Login.LoginnamePlaceHolder"}}"
|
<input class="lgn-input lgn-suffix-input" type="text" id="loginName" name="loginName" placeholder="{{t "Login.LoginnamePlaceHolder"}}"
|
||||||
value="{{ .LoginName }}" {{if .ErrMessage}}shake {{end}} autocomplete="username" autofocus required>
|
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>
|
||||||
|
@ -93,9 +93,6 @@ func (u *User) CheckOrgIamPolicy(policy *iam_model.OrgIAMPolicy) error {
|
|||||||
if policy == nil {
|
if policy == nil {
|
||||||
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-zSH7j", "Errors.Users.OrgIamPolicyNil")
|
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-zSH7j", "Errors.Users.OrgIamPolicyNil")
|
||||||
}
|
}
|
||||||
if policy.UserLoginMustBeDomain && strings.Contains(u.UserName, "@") {
|
|
||||||
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-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
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ func (es *UserEventstore) prepareCreateMachine(ctx context.Context, user *usr_mo
|
|||||||
return machine, createAggregates, err
|
return machine, createAggregates, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *UserEventstore) prepareCreateHuman(ctx context.Context, user *usr_model.User, pwPolicy *iam_model.PasswordComplexityPolicyView, orgIAMPolicy *iam_model.OrgIAMPolicyView, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
func (es *UserEventstore) prepareCreateHuman(ctx context.Context, user *usr_model.User, pwPolicy *iam_model.PasswordComplexityPolicyView, orgIAMPolicy *iam_model.OrgIAMPolicyView, changePasswordRequired bool, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
||||||
err := user.CheckOrgIAMPolicy(orgIAMPolicy)
|
err := user.CheckOrgIAMPolicy(orgIAMPolicy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -155,7 +155,7 @@ func (es *UserEventstore) prepareCreateHuman(ctx context.Context, user *usr_mode
|
|||||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-LoIxJ", "Errors.User.Invalid")
|
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-LoIxJ", "Errors.User.Invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = user.HashPasswordIfExisting(pwPolicy, es.PasswordAlg, true)
|
err = user.HashPasswordIfExisting(pwPolicy, es.PasswordAlg, changePasswordRequired)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ func (es *UserEventstore) prepareCreateHuman(ctx context.Context, user *usr_mode
|
|||||||
return repoUser, createAggregates, err
|
return repoUser, createAggregates, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model.User, pwPolicy *iam_model.PasswordComplexityPolicyView, orgIAMPolicy *iam_model.OrgIAMPolicyView, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model.User, pwPolicy *iam_model.PasswordComplexityPolicyView, orgIAMPolicy *iam_model.OrgIAMPolicyView, changePasswordRequired bool, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
||||||
id, err := es.idGenerator.Next()
|
id, err := es.idGenerator.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -185,7 +185,7 @@ func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model
|
|||||||
user.AggregateID = id
|
user.AggregateID = id
|
||||||
|
|
||||||
if user.Human != nil {
|
if user.Human != nil {
|
||||||
return es.prepareCreateHuman(ctx, user, pwPolicy, orgIAMPolicy, resourceOwner)
|
return es.prepareCreateHuman(ctx, user, pwPolicy, orgIAMPolicy, changePasswordRequired, resourceOwner)
|
||||||
} else if user.Machine != nil {
|
} else if user.Machine != nil {
|
||||||
return es.prepareCreateMachine(ctx, user, orgIAMPolicy, resourceOwner)
|
return es.prepareCreateMachine(ctx, user, orgIAMPolicy, resourceOwner)
|
||||||
}
|
}
|
||||||
@ -193,7 +193,22 @@ func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (es *UserEventstore) CreateUser(ctx context.Context, user *usr_model.User, pwPolicy *iam_model.PasswordComplexityPolicyView, orgIAMPolicy *iam_model.OrgIAMPolicyView) (*usr_model.User, error) {
|
func (es *UserEventstore) CreateUser(ctx context.Context, user *usr_model.User, pwPolicy *iam_model.PasswordComplexityPolicyView, orgIAMPolicy *iam_model.OrgIAMPolicyView) (*usr_model.User, error) {
|
||||||
repoUser, aggregates, err := es.PrepareCreateUser(ctx, user, pwPolicy, orgIAMPolicy, "")
|
repoUser, aggregates, err := es.PrepareCreateUser(ctx, user, pwPolicy, orgIAMPolicy, true, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = es_sdk.PushAggregates(ctx, es.PushAggregates, repoUser.AppendEvents, aggregates...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
es.userCache.cacheUser(repoUser)
|
||||||
|
return model.UserToModel(repoUser), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *UserEventstore) ImportUser(ctx context.Context, user *usr_model.User, pwPolicy *iam_model.PasswordComplexityPolicyView, orgIAMPolicy *iam_model.OrgIAMPolicyView, changePasswordRequired bool) (*usr_model.User, error) {
|
||||||
|
repoUser, aggregates, err := es.PrepareCreateUser(ctx, user, pwPolicy, orgIAMPolicy, changePasswordRequired, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
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;
|
@ -1020,11 +1020,13 @@ message DefaultLabelPolicy {
|
|||||||
string secondary_color = 2;
|
string secondary_color = 2;
|
||||||
google.protobuf.Timestamp creation_date = 3;
|
google.protobuf.Timestamp creation_date = 3;
|
||||||
google.protobuf.Timestamp change_date = 4;
|
google.protobuf.Timestamp change_date = 4;
|
||||||
|
bool hide_login_name_suffix = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DefaultLabelPolicyUpdate {
|
message DefaultLabelPolicyUpdate {
|
||||||
string primary_color = 1;
|
string primary_color = 1;
|
||||||
string secondary_color = 2;
|
string secondary_color = 2;
|
||||||
|
bool hide_login_name_suffix = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DefaultLabelPolicyView {
|
message DefaultLabelPolicyView {
|
||||||
@ -1032,6 +1034,7 @@ message DefaultLabelPolicyView {
|
|||||||
string secondary_color = 2;
|
string secondary_color = 2;
|
||||||
google.protobuf.Timestamp creation_date = 3;
|
google.protobuf.Timestamp creation_date = 3;
|
||||||
google.protobuf.Timestamp change_date = 4;
|
google.protobuf.Timestamp change_date = 4;
|
||||||
|
bool hide_login_name_suffix = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DefaultMailTemplate {
|
message DefaultMailTemplate {
|
||||||
|
@ -114,6 +114,17 @@ service ManagementService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpc ImportHuman(ImportHumanRequest) returns (UserResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/users/humans/_import"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (caos.zitadel.utils.v1.auth_option) = {
|
||||||
|
permission: "user.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
rpc DeactivateUser(UserID) returns (UserResponse) {
|
rpc DeactivateUser(UserID) returns (UserResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
put: "/users/{id}/_deactivate"
|
put: "/users/{id}/_deactivate"
|
||||||
@ -1809,6 +1820,58 @@ service ManagementService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpc GetLabelPolicy(google.protobuf.Empty) returns (LabelPolicyView) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/orgs/me/policies/label"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (caos.zitadel.utils.v1.auth_option) = {
|
||||||
|
permission: "policy.read"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc GetDefaultLabelPolicy(google.protobuf.Empty) returns (LabelPolicyView) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/orgs/default/policies/label"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (caos.zitadel.utils.v1.auth_option) = {
|
||||||
|
permission: "policy.read"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc CreateLabelPolicy(LabelPolicyRequest) returns (LabelPolicy) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/orgs/me/policies/label"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (caos.zitadel.utils.v1.auth_option) = {
|
||||||
|
permission: "policy.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc UpdateLabelPolicy(LabelPolicyRequest) returns (LabelPolicy) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
put: "/orgs/me/policies/label"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (caos.zitadel.utils.v1.auth_option) = {
|
||||||
|
permission: "policy.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc RemoveLabelPolicy(google.protobuf.Empty) returns (google.protobuf.Empty) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
delete: "/orgs/me/policies/label"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (caos.zitadel.utils.v1.auth_option) = {
|
||||||
|
permission: "policy.delete"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message ZitadelDocs {
|
message ZitadelDocs {
|
||||||
@ -1904,6 +1967,26 @@ message CreateUserRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ImportHumanRequest {
|
||||||
|
string user_name = 1 [(validate.rules).string.pattern = "^[^[:space:]]{1,200}$"];
|
||||||
|
string first_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string last_name = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string nick_name = 4 [(validate.rules).string = {max_len: 200}];
|
||||||
|
string preferred_language = 5 [(validate.rules).string = {max_len: 200}];
|
||||||
|
Gender gender = 6;
|
||||||
|
string email = 7 [(validate.rules).string = {min_len: 1, max_len: 200, email: true}];
|
||||||
|
bool is_email_verified = 8;
|
||||||
|
string phone = 9 [(validate.rules).string = {max_len: 20}];
|
||||||
|
bool is_phone_verified = 10;
|
||||||
|
string country = 11 [(validate.rules).string = {max_len: 200}];
|
||||||
|
string locality = 12 [(validate.rules).string = {max_len: 200}];
|
||||||
|
string postal_code = 13 [(validate.rules).string = {max_len: 200}];
|
||||||
|
string region = 14 [(validate.rules).string = {max_len: 200}];
|
||||||
|
string street_address = 15 [(validate.rules).string = {max_len: 200}];
|
||||||
|
string password = 16 [(validate.rules).string = {max_len: 72}];
|
||||||
|
bool password_change_required = 17;
|
||||||
|
}
|
||||||
|
|
||||||
message CreateHumanRequest {
|
message CreateHumanRequest {
|
||||||
string first_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
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 last_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
@ -3657,3 +3740,28 @@ message MailTextView {
|
|||||||
google.protobuf.Timestamp creation_date = 10;
|
google.protobuf.Timestamp creation_date = 10;
|
||||||
google.protobuf.Timestamp change_date = 11;
|
google.protobuf.Timestamp change_date = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message LabelPolicy {
|
||||||
|
string primary_color = 1;
|
||||||
|
string secondary_color = 2;
|
||||||
|
google.protobuf.Timestamp creation_date = 3;
|
||||||
|
google.protobuf.Timestamp change_date = 4;
|
||||||
|
bool hide_login_name_suffix = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LabelPolicyRequest {
|
||||||
|
string primary_color = 1;
|
||||||
|
string secondary_color = 2;
|
||||||
|
google.protobuf.Timestamp creation_date = 3;
|
||||||
|
google.protobuf.Timestamp change_date = 4;
|
||||||
|
bool hide_login_name_suffix = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LabelPolicyView {
|
||||||
|
bool default = 1;
|
||||||
|
string primary_color = 2;
|
||||||
|
string secondary_color = 3;
|
||||||
|
google.protobuf.Timestamp creation_date = 4;
|
||||||
|
google.protobuf.Timestamp change_date = 5;
|
||||||
|
bool hide_login_name_suffix = 6;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user