feat: Private label email policy (#813)

* Label Policy added

* save

* chore: update docs action

* Save

* Save

* Get colors from DB

* Variables inserted

* Get images from global directory.

* Add tests

* Add tests

* Corrections from mergerequest

* Corrections from mergerequest

* Test corrected.

* Added colors to all notifications.

* Added colors to
Corrected text and formatting.all notifications.

* Spelling error corrected.

* fix: tests

* Merge Branch corrected.

* Step6 added

* Corrections from mergerequest

* fix: generate management

* Formatted texts.

* fix: migrations

Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: adlerhurst <silvan.reusser@gmail.com>
Co-authored-by: Fabiennne <fabienne.gerschwiler@gmail.com>
This commit is contained in:
Michael Waeger
2020-10-20 19:10:23 +02:00
committed by GitHub
parent cfd119924f
commit 42384763d1
65 changed files with 7143 additions and 13940 deletions

View File

@@ -2,6 +2,8 @@ package eventstore
import (
"context"
"strings"
"github.com/caos/logging"
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/systemdefaults"
@@ -11,7 +13,6 @@ import (
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"strings"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
@@ -173,6 +174,24 @@ func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo
return result, nil
}
func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
policy, err := repo.View.LabelPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyViewToModel(policy), err
}
func (repo *IAMRepository) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.AddLabelPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.ChangeLabelPolicy(ctx, policy)
}
func (repo *IAMRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
policy, err := repo.View.LoginPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {

View File

@@ -1,9 +1,10 @@
package handler
import (
"time"
"github.com/caos/zitadel/internal/config/systemdefaults"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"time"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/types"
@@ -38,6 +39,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev
&IamMember{handler: handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount},
userEvents: repos.UserEvents},
&IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}},
&LabelPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount}},
&LoginPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}},
&IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount},
systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents},

View File

@@ -0,0 +1,66 @@
package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
)
type LabelPolicy struct {
handler
}
const (
labelPolicyTable = "adminapi.label_policies"
)
func (m *LabelPolicy) ViewModel() string {
return labelPolicyTable
}
func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *LabelPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case 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 model.LabelPolicyAdded:
err = policy.AppendEvent(event)
case model.LabelPolicyChanged:
policy, err = m.view.LabelPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
default:
return m.view.ProcessedLabelPolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutLabelPolicy(policy, policy.Sequence)
}
func (m *LabelPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Wj8sf", "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)
}

View File

@@ -0,0 +1,39 @@
package view
import (
"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 = "adminapi.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, sequence uint64) error {
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLabelPolicySequence(sequence)
}
func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(labelPolicyTable)
}
func (v *View) ProcessedLabelPolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(labelPolicyTable, eventSequence)
}
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)
}

View File

@@ -2,6 +2,7 @@ package repository
import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
@@ -28,6 +29,9 @@ type IAMRepository interface {
SearchDefaultIDPProviders(ctx context.Context, request *iam_model.IDPProviderSearchRequest) (*iam_model.IDPProviderSearchResponse, error)
AddIDPProviderToLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) (*iam_model.IDPProvider, error)
RemoveIDPProviderFromLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) error
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error)

View File

@@ -0,0 +1,24 @@
package admin
import (
"context"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetDefaultLabelPolicy(ctx context.Context, _ *empty.Empty) (*admin.DefaultLabelPolicyView, error) {
result, err := s.iam.GetDefaultLabelPolicy(ctx)
if err != nil {
return nil, err
}
return labelPolicyViewFromModel(result), nil
}
func (s *Server) UpdateDefaultLabelPolicy(ctx context.Context, policy *admin.DefaultLabelPolicyUpdate) (*admin.DefaultLabelPolicy, error) {
result, err := s.iam.ChangeDefaultLabelPolicy(ctx, labelPolicyToModel(policy))
if err != nil {
return nil, err
}
return labelPolicyFromModel(result), nil
}

View File

@@ -0,0 +1,45 @@
package admin
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes"
)
func labelPolicyToModel(policy *admin.DefaultLabelPolicyUpdate) *iam_model.LabelPolicy {
return &iam_model.LabelPolicy{
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
}
}
func labelPolicyFromModel(policy *iam_model.LabelPolicy) *admin.DefaultLabelPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("ADMIN-QwQG9").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("ADMIN-mAgcI").OnError(err).Debug("date parse failed")
return &admin.DefaultLabelPolicy{
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func labelPolicyViewFromModel(policy *iam_model.LabelPolicyView) *admin.DefaultLabelPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("ADMIN-zMnlF").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("ADMIN-Vhvfp").OnError(err).Debug("date parse failed")
return &admin.DefaultLabelPolicyView{
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}

View File

@@ -12,6 +12,7 @@ const (
Step3
Step4
Step5
Step6
//StepCount marks the the length of possible steps (StepCount-1 == last possible step)
StepCount
)
@@ -25,6 +26,7 @@ type IAM struct {
Members []*IAMMember
IDPs []*IDPConfig
DefaultLoginPolicy *LoginPolicy
DefaultLabelPolicy *LabelPolicy
DefaultOrgIAMPolicy *OrgIAMPolicy
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy
DefaultPasswordAgePolicy *PasswordAgePolicy

View File

@@ -0,0 +1,18 @@
package model
import (
"github.com/caos/zitadel/internal/eventstore/models"
)
type LabelPolicy struct {
models.ObjectRoot
State PolicyState
Default bool
PrimaryColor string
SecondaryColor string
}
func (p *LabelPolicy) IsValid() bool {
return p.ObjectRoot.AggregateID != ""
}

View File

@@ -0,0 +1,48 @@
package model
import (
"time"
"github.com/caos/zitadel/internal/model"
)
type LabelPolicyView struct {
AggregateID string
PrimaryColor string
SecondaryColor string
Default bool
CreationDate time.Time
ChangeDate time.Time
Sequence uint64
}
type LabelPolicySearchRequest struct {
Offset uint64
Limit uint64
SortingColumn LabelPolicySearchKey
Asc bool
Queries []*LabelPolicySearchQuery
}
type LabelPolicySearchKey int32
const (
LabelPolicySearchKeyUnspecified LabelPolicySearchKey = iota
LabelPolicySearchKeyAggregateID
)
type LabelPolicySearchQuery struct {
Key LabelPolicySearchKey
Method model.SearchMethod
Value interface{}
}
type LabelPolicySearchResponse struct {
Offset uint64
Limit uint64
TotalResult uint64
Result []*LabelPolicyView
Sequence uint64
Timestamp time.Time
}

View File

@@ -2,6 +2,7 @@ package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/cache/config"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
@@ -415,6 +416,68 @@ func (es *IAMEventstore) ChangeIDPOIDCConfig(ctx context.Context, config *iam_mo
return nil, caos_errs.ThrowInternal(nil, "EVENT-Sldk8", "Errors.Internal")
}
func (es *IAMEventstore) PrepareAddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*model.IAM, *models.Aggregate, error) {
if policy == nil || policy.AggregateID == "" {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-VwlDv", "Errors.IAM.LabelPolicy.Empty")
}
iam, err := es.IAMByID(ctx, policy.AggregateID)
if err != nil {
return nil, nil, err
}
repoIam := model.IAMFromModel(iam)
labelPolicy := model.LabelPolicyFromModel(policy)
addAggregate := LabelPolicyAddedAggregate(es.Eventstore.AggregateCreator(), repoIam, labelPolicy)
aggregate, err := addAggregate(ctx)
if err != nil {
return nil, nil, err
}
return repoIam, aggregate, nil
}
func (es *IAMEventstore) AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if policy == nil || !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-aAPWI", "Errors.IAM.LabelPolicyInvalid")
}
iam, err := es.IAMByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
repoIam := model.IAMFromModel(iam)
repoLabelPolicy := model.LabelPolicyFromModel(policy)
addAggregate := LabelPolicyAddedAggregate(es.Eventstore.AggregateCreator(), repoIam, repoLabelPolicy)
err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, addAggregate)
if err != nil {
return nil, err
}
es.iamCache.cacheIAM(repoIam)
return model.LabelPolicyToModel(repoIam.DefaultLabelPolicy), nil
}
func (es *IAMEventstore) ChangeLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if policy == nil || !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-vRqjg", "Errors.IAM.LabelPolicyInvalid")
}
iam, err := es.IAMByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
repoIam := model.IAMFromModel(iam)
repoLabelPolicy := model.LabelPolicyFromModel(policy)
addAggregate := LabelPolicyChangedAggregate(es.Eventstore.AggregateCreator(), repoIam, repoLabelPolicy)
err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, addAggregate)
if err != nil {
return nil, err
}
es.iamCache.cacheIAM(repoIam)
return model.LabelPolicyToModel(repoIam.DefaultLabelPolicy), nil
}
func (es *IAMEventstore) PrepareAddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*model.IAM, *models.Aggregate, error) {
if policy == nil || !policy.IsValid() {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-Lso02", "Errors.IAM.LoginPolicyInvalid")

View File

@@ -2,6 +2,7 @@ package eventsourcing
import (
"encoding/json"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/id"
@@ -182,3 +183,16 @@ func GetMockManipulateIAMNotExisting(ctrl *gomock.Controller) *IAMEventstore {
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
return GetMockedEventstore(ctrl, mockEs)
}
func GetMockManipulateIAMWithLabelPolicy(ctrl *gomock.Controller) *IAMEventstore {
policyData, _ := json.Marshal(model.LabelPolicy{PrimaryColor: "000001", SecondaryColor: "FFFFF1"})
events := []*es_models.Event{
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.IAMSetupStarted},
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.LabelPolicyAdded, Data: policyData},
}
mockEs := mock.NewMockEventstore(ctrl)
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
return GetMockedEventstore(ctrl, mockEs)
}

View File

@@ -1657,6 +1657,170 @@ func TestRemoveIdpProviderFromLoginPolicy(t *testing.T) {
}
}
func TestAddLabelPolicy(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *IAMEventstore
ctx context.Context
policy *iam_model.LabelPolicy
}
type res struct {
result *iam_model.LabelPolicy
wantErr bool
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "add label policy, ok",
args: args{
es: GetMockManipulateIAM(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
},
},
res: res{
result: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
},
},
},
{
name: "invalid policy",
args: args{
es: GetMockManipulateIAM(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing iam not found",
args: args{
es: GetMockManipulateIAMNotExisting(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.AddLabelPolicy(tt.args.ctx, tt.args.policy)
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err)
return
}
if tt.res.wantErr && tt.res.errFunc(err) {
return
}
if result.PrimaryColor != tt.res.result.PrimaryColor {
t.Errorf("got wrong result PrimaryColor: expected: %v, actual: %v ", tt.res.result.PrimaryColor, result.PrimaryColor)
}
})
}
}
func TestChangeLabelPolicy(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *IAMEventstore
ctx context.Context
policy *iam_model.LabelPolicy
}
type res struct {
result *iam_model.LabelPolicy
wantErr bool
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "change label policy, ok",
args: args{
es: GetMockManipulateIAMWithLabelPolicy(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
SecondaryColor: "FFFFFF",
},
},
res: res{
result: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
SecondaryColor: "FFFFFF",
},
},
},
{
name: "invalid policy",
args: args{
es: GetMockManipulateIAM(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing iam not found",
args: args{
es: GetMockManipulateIAMNotExisting(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ChangeLabelPolicy(tt.args.ctx, tt.args.policy)
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err)
return
}
if tt.res.wantErr && tt.res.errFunc(err) {
return
}
if result.PrimaryColor != tt.res.result.PrimaryColor {
t.Errorf("got wrong result PrimaryColor: expected: %v, actual: %v ", tt.res.result.PrimaryColor, result.PrimaryColor)
}
if result.SecondaryColor != tt.res.result.SecondaryColor {
t.Errorf("got wrong result SecondaryColor: expected: %v, actual: %v ", tt.res.result.SecondaryColor, result.SecondaryColor)
}
})
}
}
func TestAddPasswordComplexityPolicy(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {

View File

@@ -2,6 +2,7 @@ package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
@@ -231,6 +232,54 @@ func OIDCIDPConfigChangedAggregate(aggCreator *es_models.AggregateCreator, exist
return agg.AppendEvent(model.OIDCIDPConfigChanged, changes)
}
}
func LabelPolicyAddedAggregate(aggCreator *es_models.AggregateCreator, existing *model.IAM, policy *model.LabelPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
if policy == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-e248Y", "Errors.Internal")
}
agg, err := IAMAggregate(ctx, aggCreator, existing)
if err != nil {
return nil, err
}
validationQuery := es_models.NewSearchQuery().
AggregateTypeFilter(model.IAMAggregate).
EventTypesFilter(model.LabelPolicyAdded).
AggregateIDFilter(existing.AggregateID)
validation := checkExistingLabelPolicyValidation()
agg.SetPrecondition(validationQuery, validation)
return agg.AppendEvent(model.LabelPolicyAdded, policy)
}
}
func checkExistingLabelPolicyValidation() func(...*es_models.Event) error {
return func(events ...*es_models.Event) error {
for _, event := range events {
switch event.Type {
case model.LabelPolicyAdded:
return errors.ThrowPreconditionFailed(nil, "EVENT-KyLIK", "Errors.IAM.LabelPolicy.AlreadyExists")
}
}
return nil
}
}
func LabelPolicyChangedAggregate(aggCreator *es_models.AggregateCreator, existing *model.IAM, policy *model.LabelPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
if policy == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-uP6HQ", "Errors.Internal")
}
agg, err := IAMAggregate(ctx, aggCreator, existing)
if err != nil {
return nil, err
}
changes := existing.DefaultLabelPolicy.Changes(policy)
if len(changes) == 0 {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-hZE24", "Errors.NoChangesFound")
}
return agg.AppendEvent(model.LabelPolicyChanged, changes)
}
}
func LoginPolicyAddedAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, existing *model.IAM, policy *model.LoginPolicy) (*es_models.Aggregate, error) {
if policy == nil {

View File

@@ -30,6 +30,7 @@ type IAM struct {
Members []*IAMMember `json:"-"`
IDPs []*IDPConfig `json:"-"`
DefaultLoginPolicy *LoginPolicy `json:"-"`
DefaultLabelPolicy *LabelPolicy `json:"-"`
DefaultOrgIAMPolicy *OrgIAMPolicy `json:"-"`
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy `json:"-"`
DefaultPasswordAgePolicy *PasswordAgePolicy `json:"-"`
@@ -51,6 +52,9 @@ func IAMFromModel(iam *model.IAM) *IAM {
if iam.DefaultLoginPolicy != nil {
converted.DefaultLoginPolicy = LoginPolicyFromModel(iam.DefaultLoginPolicy)
}
if iam.DefaultLabelPolicy != nil {
converted.DefaultLabelPolicy = LabelPolicyFromModel(iam.DefaultLabelPolicy)
}
if iam.DefaultPasswordComplexityPolicy != nil {
converted.DefaultPasswordComplexityPolicy = PasswordComplexityPolicyFromModel(iam.DefaultPasswordComplexityPolicy)
}
@@ -81,6 +85,9 @@ func IAMToModel(iam *IAM) *model.IAM {
if iam.DefaultLoginPolicy != nil {
converted.DefaultLoginPolicy = LoginPolicyToModel(iam.DefaultLoginPolicy)
}
if iam.DefaultLabelPolicy != nil {
converted.DefaultLabelPolicy = LabelPolicyToModel(iam.DefaultLabelPolicy)
}
if iam.DefaultPasswordComplexityPolicy != nil {
converted.DefaultPasswordComplexityPolicy = PasswordComplexityPolicyToModel(iam.DefaultPasswordComplexityPolicy)
}
@@ -161,6 +168,10 @@ func (i *IAM) AppendEvent(event *es_models.Event) (err error) {
return i.appendAddIDPProviderToLoginPolicyEvent(event)
case LoginPolicyIDPProviderRemoved:
return i.appendRemoveIDPProviderFromLoginPolicyEvent(event)
case LabelPolicyAdded:
return i.appendAddLabelPolicyEvent(event)
case LabelPolicyChanged:
return i.appendChangeLabelPolicyEvent(event)
case PasswordComplexityPolicyAdded:
return i.appendAddPasswordComplexityPolicyEvent(event)
case PasswordComplexityPolicyChanged:

View File

@@ -0,0 +1,78 @@
package model
import (
"encoding/json"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
type LabelPolicy struct {
models.ObjectRoot
State int32 `json:"-"`
PrimaryColor string `json:"primaryColor"`
SecondaryColor string `json:"secondaryColor"`
}
func LabelPolicyToModel(policy *LabelPolicy) *iam_model.LabelPolicy {
return &iam_model.LabelPolicy{
ObjectRoot: policy.ObjectRoot,
State: iam_model.PolicyState(policy.State),
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
}
}
func LabelPolicyFromModel(policy *iam_model.LabelPolicy) *LabelPolicy {
return &LabelPolicy{
ObjectRoot: policy.ObjectRoot,
State: int32(policy.State),
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
}
}
func (p *LabelPolicy) Changes(changed *LabelPolicy) map[string]interface{} {
changes := make(map[string]interface{}, 2)
if changed.PrimaryColor != p.PrimaryColor {
changes["primaryColor"] = changed.PrimaryColor
}
if changed.SecondaryColor != p.SecondaryColor {
changes["secondaryColor"] = changed.SecondaryColor
}
return changes
}
func (i *IAM) appendAddLabelPolicyEvent(event *es_models.Event) error {
i.DefaultLabelPolicy = new(LabelPolicy)
err := i.DefaultLabelPolicy.SetDataLabel(event)
if err != nil {
return err
}
i.DefaultLabelPolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangeLabelPolicyEvent(event *es_models.Event) error {
return i.DefaultLabelPolicy.SetDataLabel(event)
}
func (p *LabelPolicy) SetDataLabel(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {
return errors.ThrowInternal(err, "MODEL-ikjhf", "unable to unmarshal data")
}
return nil
}
func (p *IDPProvider) SetDataLabel(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {
return errors.ThrowInternal(err, "MODEL-c41Hn", "unable to unmarshal data")
}
return nil
}

View File

@@ -0,0 +1,132 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/models"
)
func TestLabelPolicyChanges(t *testing.T) {
type args struct {
existing *LabelPolicy
new *LabelPolicy
}
type res struct {
changesLen int
}
tests := []struct {
name string
args args
res res
}{
{
name: "labelpolicy all attributes change",
args: args{
existing: &LabelPolicy{PrimaryColor: "000001", SecondaryColor: "FFFFFA"},
new: &LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"},
},
res: res{
changesLen: 2,
},
},
{
name: "no changes",
args: args{
existing: &LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"},
new: &LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"},
},
res: res{
changesLen: 0,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
changes := tt.args.existing.Changes(tt.args.new)
if len(changes) != tt.res.changesLen {
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
}
})
}
}
func TestAppendAddLabelPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LabelPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add label policy event",
args: args{
iam: new(IAM),
policy: &LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"},
event: new(es_models.Event),
},
result: &IAM{DefaultLabelPolicy: &LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddLabelPolicyEvent(tt.args.event)
if tt.result.DefaultLabelPolicy.PrimaryColor != tt.args.iam.DefaultLabelPolicy.PrimaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.PrimaryColor, tt.args.iam.DefaultLabelPolicy.PrimaryColor)
}
if tt.result.DefaultLabelPolicy.SecondaryColor != tt.args.iam.DefaultLabelPolicy.SecondaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.SecondaryColor, tt.args.iam.DefaultLabelPolicy.SecondaryColor)
}
})
}
}
func TestAppendChangeLabelPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LabelPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change label policy event",
args: args{
iam: &IAM{DefaultLabelPolicy: &LabelPolicy{
PrimaryColor: "000001", SecondaryColor: "FFFFF0",
}},
policy: &LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"},
event: &es_models.Event{},
},
result: &IAM{DefaultLabelPolicy: &LabelPolicy{
PrimaryColor: "000000", SecondaryColor: "FFFFFF",
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangeLabelPolicyEvent(tt.args.event)
if tt.result.DefaultLabelPolicy.PrimaryColor != tt.args.iam.DefaultLabelPolicy.PrimaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.PrimaryColor, tt.args.iam.DefaultLabelPolicy.PrimaryColor)
}
if tt.result.DefaultLabelPolicy.SecondaryColor != tt.args.iam.DefaultLabelPolicy.SecondaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.SecondaryColor, tt.args.iam.DefaultLabelPolicy.SecondaryColor)
}
})
}
}

View File

@@ -30,6 +30,8 @@ const (
LoginPolicyIDPProviderAdded models.EventType = "iam.policy.login.idpprovider.added"
LoginPolicyIDPProviderRemoved models.EventType = "iam.policy.login.idpprovider.removed"
LoginPolicyIDPProviderCascadeRemoved models.EventType = "iam.policy.login.idpprovider.cascade.removed"
LabelPolicyAdded models.EventType = "iam.policy.label.added"
LabelPolicyChanged models.EventType = "iam.policy.label.changed"
PasswordComplexityPolicyAdded models.EventType = "iam.policy.password.complexity.added"
PasswordComplexityPolicyChanged models.EventType = "iam.policy.password.complexity.changed"

View File

@@ -0,0 +1,32 @@
package view
import (
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_model "github.com/caos/zitadel/internal/model"
"github.com/caos/zitadel/internal/view/repository"
"github.com/jinzhu/gorm"
)
func GetLabelPolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.LabelPolicyView, error) {
policy := new(model.LabelPolicyView)
userIDQuery := &model.LabelPolicySearchQuery{Key: iam_model.LabelPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
query := repository.PrepareGetByQuery(table, userIDQuery)
err := query(db, policy)
if caos_errs.IsNotFound(err) {
return nil, caos_errs.ThrowNotFound(nil, "VIEW-68G11", "Errors.IAM.LabelPolicy.NotExisting")
}
return policy, err
}
func PutLabelPolicy(db *gorm.DB, table string, policy *model.LabelPolicyView) error {
save := repository.PrepareSave(table)
return save(db, policy)
}
func DeleteLabelPolicy(db *gorm.DB, table, aggregateID string) error {
delete := repository.PrepareDeleteByKey(table, model.LabelPolicySearchKey(iam_model.LabelPolicySearchKeyAggregateID), aggregateID)
return delete(db)
}

View File

@@ -0,0 +1,82 @@
package model
import (
"encoding/json"
"time"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/iam/model"
)
const (
LabelPolicyKeyAggregateID = "aggregate_id"
)
type LabelPolicyView struct {
AggregateID string `json:"-" gorm:"column:aggregate_id;primary_key"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
State int32 `json:"-" gorm:"column:label_policy_state"`
PrimaryColor string `json:"primaryColor" gorm:"column:primary_color"`
SecondaryColor string `json:"secondaryColor" gorm:"column:secondary_color"`
Default bool `json:"-" gorm:"-"`
Sequence uint64 `json:"-" gorm:"column:sequence"`
}
func LabelPolicyViewFromModel(policy *model.LabelPolicyView) *LabelPolicyView {
return &LabelPolicyView{
AggregateID: policy.AggregateID,
Sequence: policy.Sequence,
CreationDate: policy.CreationDate,
ChangeDate: policy.ChangeDate,
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
Default: policy.Default,
}
}
func LabelPolicyViewToModel(policy *LabelPolicyView) *model.LabelPolicyView {
return &model.LabelPolicyView{
AggregateID: policy.AggregateID,
Sequence: policy.Sequence,
CreationDate: policy.CreationDate,
ChangeDate: policy.ChangeDate,
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
Default: policy.Default,
}
}
func (i *LabelPolicyView) AppendEvent(event *models.Event) (err error) {
i.Sequence = event.Sequence
i.ChangeDate = event.CreationDate
switch event.Type {
case es_model.LabelPolicyAdded, org_es_model.LabelPolicyAdded:
i.setRootData(event)
i.CreationDate = event.CreationDate
err = i.SetData(event)
case es_model.LabelPolicyChanged, org_es_model.LabelPolicyChanged:
err = i.SetData(event)
}
return err
}
func (r *LabelPolicyView) setRootData(event *models.Event) {
r.AggregateID = event.AggregateID
}
func (r *LabelPolicyView) SetData(event *models.Event) error {
if err := json.Unmarshal(event.Data, r); err != nil {
logging.Log("MODEL-Flp9C").WithError(err).Error("could not unmarshal event data")
return caos_errs.ThrowInternal(err, "MODEL-Hs8uf", "Could not unmarshal data")
}
return nil
}

View File

@@ -0,0 +1,59 @@
package model
import (
iam_model "github.com/caos/zitadel/internal/iam/model"
global_model "github.com/caos/zitadel/internal/model"
"github.com/caos/zitadel/internal/view/repository"
)
type LabelPolicySearchRequest iam_model.LabelPolicySearchRequest
type LabelPolicySearchQuery iam_model.LabelPolicySearchQuery
type LabelPolicySearchKey iam_model.LabelPolicySearchKey
func (req LabelPolicySearchRequest) GetLimit() uint64 {
return req.Limit
}
func (req LabelPolicySearchRequest) GetOffset() uint64 {
return req.Offset
}
func (req LabelPolicySearchRequest) GetSortingColumn() repository.ColumnKey {
if req.SortingColumn == iam_model.LabelPolicySearchKeyUnspecified {
return nil
}
return LabelPolicySearchKey(req.SortingColumn)
}
func (req LabelPolicySearchRequest) GetAsc() bool {
return req.Asc
}
func (req LabelPolicySearchRequest) GetQueries() []repository.SearchQuery {
result := make([]repository.SearchQuery, len(req.Queries))
for i, q := range req.Queries {
result[i] = LabelPolicySearchQuery{Key: q.Key, Value: q.Value, Method: q.Method}
}
return result
}
func (req LabelPolicySearchQuery) GetKey() repository.ColumnKey {
return LabelPolicySearchKey(req.Key)
}
func (req LabelPolicySearchQuery) GetMethod() global_model.SearchMethod {
return req.Method
}
func (req LabelPolicySearchQuery) GetValue() interface{} {
return req.Value
}
func (key LabelPolicySearchKey) ToColumnName() string {
switch iam_model.LabelPolicySearchKey(key) {
case iam_model.LabelPolicySearchKeyAggregateID:
return LabelPolicyKeyAggregateID
default:
return ""
}
}

View File

@@ -2,25 +2,25 @@ package eventstore
import (
"context"
"strings"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
usr_model "github.com/caos/zitadel/internal/user/model"
"strings"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/sdk"
mgmt_view "github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
global_model "github.com/caos/zitadel/internal/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view/model"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
@@ -302,6 +302,31 @@ func (repo *OrgRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo
return result, nil
}
func (repo *OrgRepository) GetLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
policy, err := repo.View.LabelPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {
policy, err = repo.View.LabelPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
policy.Default = true
}
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyViewToModel(policy), err
}
func (repo *OrgRepository) AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = authz.GetCtxData(ctx).OrgID
return repo.OrgEventstore.AddLabelPolicy(ctx, policy)
}
func (repo *OrgRepository) ChangeLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = authz.GetCtxData(ctx).OrgID
return repo.OrgEventstore.ChangeLabelPolicy(ctx, policy)
}
func (repo *OrgRepository) GetLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
policy, err := repo.View.LoginPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {

View File

@@ -61,6 +61,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev
&MachineKeys{handler: handler{view, bulkLimit, configs.cycleDuration("MachineKeys"), errorCount}},
&IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}},
&LoginPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}},
&LabelPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount}},
&IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount},
systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents},
&ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount},

View File

@@ -0,0 +1,67 @@
package handler
import (
"github.com/caos/logging"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
type LabelPolicy struct {
handler
}
const (
labelPolicyTable = "management.label_policies"
)
func (m *LabelPolicy) ViewModel() string {
return labelPolicyTable
}
func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate).
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.Sequence)
}
if err != nil {
return err
}
return m.view.PutLabelPolicy(policy, policy.Sequence)
}
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)
}

View File

@@ -0,0 +1,48 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
"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 = "management.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, sequence uint64) error {
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLabelPolicySequence(sequence)
}
func (v *View) DeleteLabelPolicy(aggregateID string, eventSequence uint64) error {
err := view.DeleteLabelPolicy(v.Db, labelPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedLabelPolicySequence(eventSequence)
}
func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(labelPolicyTable)
}
func (v *View) ProcessedLabelPolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(labelPolicyTable, eventSequence)
}
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)
}

View File

@@ -10,11 +10,14 @@ import (
"github.com/caos/zitadel/internal/api/authz"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/i18n"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/notification/types"
"github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
@@ -32,8 +35,10 @@ type Notification struct {
}
const (
notificationTable = "notification.notifications"
NotifyUserID = "NOTIFICATION"
notificationTable = "notification.notifications"
NotifyUserID = "NOTIFICATION"
labelPolicyTableOrg = "management.label_policies"
labelPolicyTableDef = "adminapi.label_policies"
)
func (n *Notification) ViewModel() string {
@@ -78,13 +83,19 @@ func (n *Notification) handleInitUserCode(event *models.Event) (err error) {
if err != nil || alreadyHandled {
return err
}
colors, err := n.getLabelPolicy(context.Background())
if err != nil {
return err
}
initCode := new(es_model.InitUserCode)
initCode.SetData(event)
user, err := n.view.NotifyUserByID(event.AggregateID)
if err != nil {
return err
}
err = types.SendUserInitCode(n.statikDir, n.i18n, user, initCode, n.systemDefaults, n.AesCrypto)
err = types.SendUserInitCode(n.statikDir, n.i18n, user, initCode, n.systemDefaults, n.AesCrypto, colors)
if err != nil {
return err
}
@@ -96,13 +107,19 @@ func (n *Notification) handlePasswordCode(event *models.Event) (err error) {
if err != nil || alreadyHandled {
return err
}
colors, err := n.getLabelPolicy(context.Background())
if err != nil {
return err
}
pwCode := new(es_model.PasswordCode)
pwCode.SetData(event)
user, err := n.view.NotifyUserByID(event.AggregateID)
if err != nil {
return err
}
err = types.SendPasswordCode(n.statikDir, n.i18n, user, pwCode, n.systemDefaults, n.AesCrypto)
err = types.SendPasswordCode(n.statikDir, n.i18n, user, pwCode, n.systemDefaults, n.AesCrypto, colors)
if err != nil {
return err
}
@@ -114,13 +131,19 @@ func (n *Notification) handleEmailVerificationCode(event *models.Event) (err err
if err != nil || alreadyHandled {
return nil
}
colors, err := n.getLabelPolicy(context.Background())
if err != nil {
return err
}
emailCode := new(es_model.EmailCode)
emailCode.SetData(event)
user, err := n.view.NotifyUserByID(event.AggregateID)
if err != nil {
return err
}
err = types.SendEmailVerificationCode(n.statikDir, n.i18n, user, emailCode, n.systemDefaults, n.AesCrypto)
err = types.SendEmailVerificationCode(n.statikDir, n.i18n, user, emailCode, n.systemDefaults, n.AesCrypto, colors)
if err != nil {
return err
}
@@ -196,3 +219,21 @@ func (n *Notification) OnError(event *models.Event, err error) error {
func getSetNotifyContextData(orgID string) context.Context {
return authz.SetCtxData(context.Background(), authz.CtxData{UserID: NotifyUserID, OrgID: orgID})
}
// Read organization specific colors
func (n *Notification) getLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
// read from Org
policy, err := n.view.LabelPolicyByAggregateID(authz.GetCtxData(ctx).OrgID, labelPolicyTableOrg)
if errors.IsNotFound(err) {
// read from default
policy, err = n.view.LabelPolicyByAggregateID(n.systemDefaults.IamID, labelPolicyTableDef)
if err != nil {
return nil, err
}
policy.Default = true
}
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyViewToModel(policy), err
}

View File

@@ -0,0 +1,10 @@
package view
import (
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
)
func (v *View) LabelPolicyByAggregateID(aggregateID string, labelPolicyTableVar string) (*model.LabelPolicyView, error) {
return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTableVar, aggregateID)
}

View File

@@ -3,28 +3,28 @@ InitCode:
PreHeader: User initialisieren
Subject: User initialisieren
Greeting: Hallo {{.FirstName}} {{.LastName}},
Text: Dieser Benutzer wurde soeben im Zitadel erstellt. Mit dem Benutzernamen {{.PreferredLoginName}} kannst du dich anmelden. Nutze den untenstehenden Button, um die Initialisierung abzuschliesen. (Code {{.Code}}) Falls du dieses Mail nicht angefordert hast, kannst du es einfach ignorieren.
Text: Dieser Benutzer wurde soeben im Zitadel erstellt. Mit dem Benutzernamen &lt;br&gt;&lt;strong&gt;{{.PreferredLoginName}}&lt;/strong&gt;&lt;br&gt; kannst du dich anmelden. Nutze den untenstehenden Button, um die Initialisierung abzuschliessen &lt;br&gt;(Code &lt;strong&gt;{{.Code}}&lt;/strong&gt;).&lt;br&gt; Falls du dieses Mail nicht angefordert hast, kannst du es einfach ignorieren.
ButtonText: Initialisierung abschliessen
PasswordReset:
Title: Zitadel - Passwort zurücksetzen
PreHeader: Passwort zurücksetzen
Subject: Passwort zurücksetzen
Greeting: Hallo {{.FirstName}} {{.LastName}},
Text: Wir haben eine Anfrage für das Zurücksetzen deines Passwortes bekommen. Du kannst den untenstehenden Button verwenden, um dein Passwort zurückzusetzen. (Code {{.Code}}) Falls du dieses Mail nicht angefordert hast, kannst du es ignorieren.
Text: Wir haben eine Anfrage für das Zurücksetzen deines Passwortes bekommen. Du kannst den untenstehenden Button verwenden, um dein Passwort zurückzusetzen &lt;br&gt;(Code &lt;strong&gt;{{.Code}}&lt;/strong&gt;).&lt;br&gt; Falls du dieses Mail nicht angefordert hast, kannst du es ignorieren.
ButtonText: Passwort zurücksetzen
VerifyEmail:
Title: Zitadel - Email verifizieren
PreHeader: Email verifizieren
Subject: Email verifizieren
Greeting: Hallo {{.FirstName}} {{.LastName}},
Text: Eine neue E-Mail Adresse wurde hinzugefügt. Bitte verwende den untenstehenden Button um diese zu verifizieren. (Code {{.Code}}) Falls du deine E-Mail Adresse nicht selber hinzugefügt hast, kannst du dieses E-Mail ignorieren.
Text: Eine neue E-Mail Adresse wurde hinzugefügt. Bitte verwende den untenstehenden Button um diese zu verifizieren &lt;br&gt;(Code &lt;strong&gt;{{.Code}}&lt;/strong&gt;).&lt;br&gt; Falls du deine E-Mail Adresse nicht selber hinzugefügt hast, kannst du dieses E-Mail ignorieren.
ButtonText: Email verifizieren
VerifyPhone:
Title: Zitadel - Telefonnummer verifizieren
PreHeader: Telefonnummer verifizieren
Subject: Telefonnummer verifizieren
Greeting: Hallo {{.FirstName}} {{.LastName}},
Text: Eine Telefonnummer wurde hinzugefügt. Bitte verifiziere diese in dem du folgenden Code eingibst {{.Code}}
Text: Eine Telefonnummer wurde hinzugefügt. Bitte verifiziere diese in dem du folgenden Code eingibst&lt;br&gt;(Code &lt;strong&gt;{{.Code}}&lt;/strong&gt;).&lt;br&gt;
ButtonText: Telefon verifizieren
DomainClaimed:
Title: Zitadel - Domain wurde beansprucht

View File

@@ -0,0 +1,49 @@
<mjml>
<mj-head>
<mj-attributes>
<mj-text align="center" color="#ffffff" font-family="Lato" />
<mj-section padding="0" full-width="full-width" />
<mj-body background-color="#222324" />
<mj-image padding="0" />
<mj-column padding="0" />
<mj-wrapper padding-left="0" />
<mj-wrapper full-width="full-width" />
<mj-class name="left" position="" />
</mj-attributes>
</mj-head>
<mj-body>
<mj-wrapper background-url="https://static.zitadel.ch/zitadel-logo-outline-light.png" border="0" background-repeat="no-repeat">
<mj-section>
<mj-group>
<mj-column>
<mj-image src="https://static.zitadel.ch/zitadel-logo-light.png" align="left" width="100px" padding="0" />
</mj-column>
</mj-group>
</mj-section>
<mj-section>
<mj-group>
<mj-column width="20%">
<mj-image src="https://static.zitadel.ch/flavor-spikes-small-opacity40.png" align="left" heigh="80%" width="80%" />
</mj-column>
<mj-column width="60%">
<mj-text font-size="2rem" font-weight="light">{{.Greeting}}</mj-text>
<mj-text font-size="1.25rem" font-weight="light">{{.Text}}</mj-text>
<mj-button href="{{.URL}}" background-color="#5282C1" font-size="16px">{{.ButtonText}}</mj-button>
<mj-text>
<a href="http://www.caos.ch" style="color:#e91e63; text-decoration: none;" target="_blank"> CAOS AG </a> | Teufener Strasse 19 | CH-9000 St. Gallen </mj-text>
</mj-column>
<mj-column width="20%">
<mj-image src="https://static.zitadel.ch/flavor-spikes-big-opacity40.png" align="right" />
</mj-column>
</mj-group>
</mj-section>
<mj-section>
<mj-group>
<mj-column>
<mj-image src="https://static.zitadel.ch/logo_whitefont_transparentbg.png" align="right" heigh="65%" width="65%" padding-right="20px" />
</mj-column>
</mj-group>
</mj-section>
</mj-wrapper>
</mj-body>
</mjml>

View File

@@ -0,0 +1,49 @@
<mjml>
<mj-head>
<mj-attributes>
<mj-text align="center" color="#555" font-family="Lato" />
<mj-section padding="0" full-width="full-width" />
<mj-body />
<mj-image padding="0" />
<mj-column padding="0" />
<mj-wrapper padding-left="0" />
<mj-wrapper full-width="full-width" />
<mj-class name="left" position="" />
</mj-attributes>
</mj-head>
<mj-body>
<mj-wrapper background-url="https://static.zitadel.ch/zitadel-logo-outline-dark.png" border="0" background-repeat="no-repeat">
<mj-section>
<mj-group>
<mj-column>
<mj-image src="https://static.zitadel.ch/zitadel-logo-dark.png" align="left" width="100px" padding="0" />
</mj-column>
</mj-group>
</mj-section>
<mj-section>
<mj-group>
<mj-column width="20%">
<mj-image src="https://static.zitadel.ch/flavor-spikes-small-opacity40.png" align="left" />
</mj-column>
<mj-column width="60%">
<mj-text font-size="2rem" font-weight="light">{{.Greeting}}</mj-text>
<mj-text font-size="1.25rem" font-weight="light">{{.Text}}</mj-text>
<mj-button href="{{.URL}}" background-color="#5282C1" font-size="16px">{{.ButtonText}}</mj-button>
<mj-text>
<a href="http://www.caos.ch" style="color:#e91e63; text-decoration: none;" target="_blank"> CAOS AG </a> | Teufener Strasse 19 | CH-9000 St. Gallen </mj-text>
</mj-column>
<mj-column width="20%">
<mj-image src="https://static.zitadel.ch/flavor-spikes-big-opacity40.png" align="right" />
</mj-column>
</mj-group>
</mj-section>
<mj-section>
<mj-group>
<mj-column>
<mj-image src="https://static.zitadel.ch/logo-gsuite-light.png" align="right" width="100px" />
</mj-column>
</mj-group>
</mj-section>
</mj-wrapper>
</mj-body>
</mjml>

View File

@@ -0,0 +1,32 @@
<mjml>
<mj-head>
<mj-attributes>
<mj-text align="center" color="#555" font-family="Lato" />
<mj-section full-width="full-width" />
<mj-body />
<mj-image padding="0" />
<mj-column />
<mj-class name="left" align="left" position="absolute" width="50%" />
<mj-class name="right" align="right" />
<mj-class name="position" position="absolute" />
<mj-class name="body" background-image="url('https://static.zitadel.ch/logo-gsuite-light.png')" />
</mj-attributes>
</mj-head>
<mj-body mj-class="body">
<mj-section background-url="https://static.zitadel.ch/zitadel-logo-outline-dark.png" border="0" background-repeat="no-repeat">
<mj-group>
<mj-column>
<mj-image src="https://static.zitadel.ch/zitadel-logo-dark.png" width="100px" padding="0" mj-class="left" />
<mj-image src="https://static.zitadel.ch/flavor-spikes-small-opacity40.png" mj-class="left position" />
<mj-text font-size="2rem" font-weight="light">{{.Greeting}}</mj-text>
<mj-text font-size="1.25rem" font-weight="light">{{.Text}}</mj-text>
<mj-button href="{{.URL}}" background-color="#5282C1" font-size="16px">{{.ButtonText}}</mj-button>
<mj-text>
<a href="http://www.caos.ch" style="color:#e91e63; text-decoration: none;" target="_blank"> CAOS AG </a> | Teufener Strasse 19 | CH-9000 St. Gallen </mj-text>
<mj-image src="https://static.zitadel.ch/flavor-spikes-big-opacity40.png" width="50%" mj-class="right position" />
<mj-image src="https://static.zitadel.ch/logo-gsuite-light.png" width="100px" padding="0" mj-class="right" />
</mj-column>
</mj-group>
</mj-section>
</mj-body>
</mjml>

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,21 @@
package templates
import (
"html"
"github.com/caos/zitadel/internal/i18n"
)
type TemplateData struct {
Title string
PreHeader string
Subject string
Greeting string
Text string
Href string
ButtonText string
Title string
PreHeader string
Subject string
Greeting string
Text string
Href string
ButtonText string
PrimaryColor string
SecondaryColor string
}
func (data *TemplateData) Translate(i18n *i18n.Translator, args map[string]interface{}, langs ...string) {
@@ -19,7 +23,7 @@ func (data *TemplateData) Translate(i18n *i18n.Translator, args map[string]inter
data.PreHeader = i18n.Localize(data.PreHeader, nil, langs...)
data.Subject = i18n.Localize(data.Subject, nil, langs...)
data.Greeting = i18n.Localize(data.Greeting, args, langs...)
data.Text = i18n.Localize(data.Text, args, langs...)
data.Text = html.UnescapeString(i18n.Localize(data.Text, args, langs...))
data.Href = i18n.Localize(data.Href, nil, langs...)
data.ButtonText = i18n.Localize(data.ButtonText, nil, langs...)
}

View File

@@ -1,13 +1,15 @@
package types
import (
"net/http"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/i18n"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/notification/templates"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"net/http"
)
type EmailVerificationCodeData struct {
@@ -15,7 +17,7 @@ type EmailVerificationCodeData struct {
URL string
}
func SendEmailVerificationCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm) error {
func SendEmailVerificationCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
codeString, err := crypto.DecryptString(code.Code, alg)
if err != nil {
return err
@@ -32,6 +34,9 @@ func SendEmailVerificationCode(dir http.FileSystem, i18n *i18n.Translator, user
systemDefaults.Notifications.TemplateData.VerifyEmail.Translate(i18n, args, user.PreferredLanguage)
emailCodeData := &EmailVerificationCodeData{TemplateData: systemDefaults.Notifications.TemplateData.VerifyEmail, URL: url}
// Set the color in initCodeData
emailCodeData.PrimaryColor = colors.PrimaryColor
emailCodeData.SecondaryColor = colors.SecondaryColor
template, err := templates.GetParsedTemplate(dir, emailCodeData)
if err != nil {
return err

View File

@@ -1,13 +1,15 @@
package types
import (
"net/http"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/i18n"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/notification/templates"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"net/http"
)
type InitCodeEmailData struct {
@@ -21,7 +23,7 @@ type UrlData struct {
PasswordSet bool
}
func SendUserInitCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm) error {
func SendUserInitCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
codeString, err := crypto.DecryptString(code.Code, alg)
if err != nil {
return err
@@ -39,6 +41,9 @@ func SendUserInitCode(dir http.FileSystem, i18n *i18n.Translator, user *view_mod
systemDefaults.Notifications.TemplateData.InitCode.Translate(i18n, args, user.PreferredLanguage)
initCodeData := &InitCodeEmailData{TemplateData: systemDefaults.Notifications.TemplateData.InitCode, URL: url}
// Set the color in initCodeData
initCodeData.PrimaryColor = colors.PrimaryColor
initCodeData.SecondaryColor = colors.SecondaryColor
template, err := templates.GetParsedTemplate(dir, initCodeData)
if err != nil {
return err

View File

@@ -1,13 +1,15 @@
package types
import (
"net/http"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/i18n"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/notification/templates"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"net/http"
)
type PasswordCodeData struct {
@@ -17,7 +19,7 @@ type PasswordCodeData struct {
URL string
}
func SendPasswordCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm) error {
func SendPasswordCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
codeString, err := crypto.DecryptString(code.Code, alg)
if err != nil {
return err
@@ -34,6 +36,9 @@ func SendPasswordCode(dir http.FileSystem, i18n *i18n.Translator, user *view_mod
systemDefaults.Notifications.TemplateData.PasswordReset.Translate(i18n, args, user.PreferredLanguage)
passwordCodeData := &PasswordCodeData{TemplateData: systemDefaults.Notifications.TemplateData.PasswordReset, FirstName: user.FirstName, LastName: user.LastName, URL: url}
// Set the color in initCodeData
passwordCodeData.PrimaryColor = colors.PrimaryColor
passwordCodeData.SecondaryColor = colors.SecondaryColor
template, err := templates.GetParsedTemplate(dir, passwordCodeData)
if err != nil {
return err

View File

@@ -1,6 +1,8 @@
package types
import (
"html"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/notification/providers"
@@ -14,6 +16,7 @@ func generateEmail(user *view_model.NotifyUser, subject, content string, config
if err != nil {
return err
}
content = html.UnescapeString(content)
message := &email.EmailMessage{
SenderEmail: config.Providers.Email.From,
Recipients: []string{user.VerifiedEmail},

View File

@@ -1,10 +1,11 @@
package model
import (
"strings"
es_models "github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/golang/protobuf/ptypes/timestamp"
"strings"
)
type Org struct {
@@ -17,6 +18,7 @@ type Org struct {
Members []*OrgMember
OrgIamPolicy *iam_model.OrgIAMPolicy
LoginPolicy *iam_model.LoginPolicy
LabelPolicy *iam_model.LabelPolicy
PasswordComplexityPolicy *iam_model.PasswordComplexityPolicy
PasswordAgePolicy *iam_model.PasswordAgePolicy
PasswordLockoutPolicy *iam_model.PasswordLockoutPolicy

View File

@@ -705,6 +705,46 @@ func (es *OrgEventstore) ChangeIDPOIDCConfig(ctx context.Context, config *iam_mo
return nil, errors.ThrowInternal(nil, "EVENT-Sldk8", "Errors.Internal")
}
func (es *OrgEventstore) AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if policy == nil || !policy.IsValid() {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-37rSC", "Errors.Org.LabelPolicyInvalid")
}
org, err := es.OrgByID(ctx, org_model.NewOrg(policy.AggregateID))
if err != nil {
return nil, err
}
repoOrg := model.OrgFromModel(org)
repoLabelPolicy := iam_es_model.LabelPolicyFromModel(policy)
addAggregate := LabelPolicyAddedAggregate(es.Eventstore.AggregateCreator(), repoOrg, repoLabelPolicy)
err = es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyToModel(repoOrg.LabelPolicy), nil
}
func (es *OrgEventstore) ChangeLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if policy == nil || !policy.IsValid() {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-0NBIw", "Errors.Org.LabelPolicyInvalid")
}
org, err := es.OrgByID(ctx, org_model.NewOrg(policy.AggregateID))
if err != nil {
return nil, err
}
repoOrg := model.OrgFromModel(org)
repoLabelPolicy := iam_es_model.LabelPolicyFromModel(policy)
addAggregate := LabelPolicyChangedAggregate(es.Eventstore.AggregateCreator(), repoOrg, repoLabelPolicy)
err = es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyToModel(repoOrg.LabelPolicy), nil
}
func (es *OrgEventstore) AddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
if policy == nil || !policy.IsValid() {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-Sjkl9", "Errors.Org.LoginPolicy.Invalid")

View File

@@ -2,6 +2,7 @@ package eventsourcing
import (
"encoding/json"
"github.com/caos/zitadel/internal/crypto"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
@@ -157,3 +158,17 @@ func GetMockChangesOrgWithPasswordAgePolicy(ctrl *gomock.Controller) *OrgEventst
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
return GetMockedEventstore(ctrl, mockEs)
}
func GetMockChangesOrgWithLabelPolicy(ctrl *gomock.Controller) *OrgEventstore {
orgData, _ := json.Marshal(model.Org{Name: "MusterOrg"})
labelPolicy, _ := json.Marshal(iam_es_model.LabelPolicy{PrimaryColor: "000001", SecondaryColor: "FFFFF1"})
events := []*es_models.Event{
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.OrgAdded, Data: orgData},
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.LabelPolicyAdded, Data: labelPolicy},
}
mockEs := mock.NewMockEventstore(ctrl)
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
return GetMockedEventstore(ctrl, mockEs)
}

View File

@@ -3,10 +3,11 @@ package eventsourcing
import (
"context"
"encoding/json"
iam_model "github.com/caos/zitadel/internal/iam/model"
"testing"
"time"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
@@ -2731,6 +2732,170 @@ func TestRemoveIdpProviderFromLoginPolicy(t *testing.T) {
}
}
func TestAddLabelPolicy(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *OrgEventstore
ctx context.Context
policy *iam_model.LabelPolicy
}
type res struct {
result *iam_model.LabelPolicy
wantErr bool
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "add label policy, ok",
args: args{
es: GetMockChangesOrgOK(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
},
},
res: res{
result: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
},
},
},
{
name: "invalid policy",
args: args{
es: GetMockChangesOrgOK(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing org not found",
args: args{
es: GetMockChangesOrgNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.AddLabelPolicy(tt.args.ctx, tt.args.policy)
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err)
return
}
if tt.res.wantErr && tt.res.errFunc(err) {
return
}
if result.PrimaryColor != tt.res.result.PrimaryColor {
t.Errorf("got wrong result PrimaryColor: expected: %v, actual: %v ", tt.res.result.PrimaryColor, result.PrimaryColor)
}
})
}
}
func TestChangeLabelPolicy(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *OrgEventstore
ctx context.Context
policy *iam_model.LabelPolicy
}
type res struct {
result *iam_model.LabelPolicy
wantErr bool
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "add label policy, ok",
args: args{
es: GetMockChangesOrgWithLabelPolicy(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
SecondaryColor: "FFFFFF",
},
},
res: res{
result: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
PrimaryColor: "000000",
SecondaryColor: "FFFFFF",
},
},
},
{
name: "invalid policy",
args: args{
es: GetMockChangesOrgOK(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing iam not found",
args: args{
es: GetMockChangesOrgNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
},
},
res: res{
wantErr: true,
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ChangeLabelPolicy(tt.args.ctx, tt.args.policy)
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err)
return
}
if tt.res.wantErr && tt.res.errFunc(err) {
return
}
if result.PrimaryColor != tt.res.result.PrimaryColor {
t.Errorf("got wrong result PrimaryColor: expected: %v, actual: %v ", tt.res.result.PrimaryColor, result.PrimaryColor)
}
if result.SecondaryColor != tt.res.result.SecondaryColor {
t.Errorf("got wrong result SecondaryColor: expected: %v, actual: %v ", tt.res.result.SecondaryColor, result.SecondaryColor)
}
})
}
}
func TestAddPasswordComplexityPolicy(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {

View File

@@ -0,0 +1,77 @@
package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
func LabelPolicyAddedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org, policy *iam_es_model.LabelPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
if policy == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-TUWod", "Errors.Internal")
}
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
if err != nil {
return nil, err
}
validationQuery := es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate).
AggregateIDFilter(existing.AggregateID)
validation := checkExistingLabelPolicyValidation()
agg.SetPrecondition(validationQuery, validation)
return agg.AppendEvent(model.LabelPolicyAdded, policy)
}
}
func LabelPolicyChangedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org, policy *iam_es_model.LabelPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
if policy == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-unRI2", "Errors.Internal")
}
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
if err != nil {
return nil, err
}
changes := existing.LabelPolicy.Changes(policy)
if len(changes) == 0 {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-Tz130", "Errors.NoChangesFound")
}
return agg.AppendEvent(model.LabelPolicyChanged, changes)
}
}
func LabelPolicyRemovedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
if existing == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-v7E9b", "Errors.Internal")
}
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
if err != nil {
return nil, err
}
return agg.AppendEvent(model.LabelPolicyRemoved, nil)
}
}
func checkExistingLabelPolicyValidation() func(...*es_models.Event) error {
return func(events ...*es_models.Event) error {
existing := false
for _, event := range events {
switch event.Type {
case model.LabelPolicyAdded:
existing = true
case model.LabelPolicyRemoved:
existing = false
}
}
if existing {
return errors.ThrowPreconditionFailed(nil, "EVENT-g9mCI", "Errors.Org.LabelPolicy.AlreadyExists")
}
return nil
}
}

View File

@@ -0,0 +1,186 @@
package eventsourcing
import (
"context"
"testing"
"github.com/caos/zitadel/internal/api/authz"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
func TestLabelPolicyAddedAggregate(t *testing.T) {
type args struct {
ctx context.Context
existing *model.Org
new *iam_es_model.LabelPolicy
aggCreator *models.AggregateCreator
}
type res struct {
eventLen int
eventTypes []models.EventType
wantErr bool
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "add label polciy",
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existing: &model.Org{
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
},
new: &iam_es_model.LabelPolicy{
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
PrimaryColor: "000000",
},
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
eventLen: 1,
eventTypes: []models.EventType{model.LabelPolicyAdded},
},
},
{
name: "existing org nil",
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existing: nil,
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "label policy config nil",
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existing: &model.Org{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}},
new: nil,
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
agg, err := LabelPolicyAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
}
for i := 0; i < tt.res.eventLen; i++ {
if !tt.res.wantErr && agg.Events[i].Type != tt.res.eventTypes[i] {
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], agg.Events[i].Type.String())
}
if !tt.res.wantErr && agg.Events[i].Data == nil {
t.Errorf("should have data in event")
}
}
if tt.res.wantErr && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestLabelPolicyChangedAggregate(t *testing.T) {
type args struct {
ctx context.Context
existing *model.Org
new *iam_es_model.LabelPolicy
aggCreator *models.AggregateCreator
}
type res struct {
eventLen int
eventTypes []models.EventType
wantErr bool
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "change label policy",
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existing: &model.Org{
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
LabelPolicy: &iam_es_model.LabelPolicy{
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
},
},
new: &iam_es_model.LabelPolicy{
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
PrimaryColor: "000000",
SecondaryColor: "FFFFFF",
},
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
eventLen: 1,
eventTypes: []models.EventType{model.LabelPolicyChanged},
},
},
{
name: "existing org nil",
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existing: nil,
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "label policy config nil",
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existing: &model.Org{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}},
new: nil,
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
wantErr: true,
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
agg, err := LabelPolicyChangedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
}
for i := 0; i < tt.res.eventLen; i++ {
if !tt.res.wantErr && agg.Events[i].Type != tt.res.eventTypes[i] {
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], agg.Events[i].Type.String())
}
if !tt.res.wantErr && agg.Events[i].Data == nil {
t.Errorf("should have data in event")
}
}
if tt.res.wantErr && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}

View File

@@ -0,0 +1,24 @@
package model
import (
es_models "github.com/caos/zitadel/internal/eventstore/models"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
)
func (o *Org) appendAddLabelPolicyEvent(event *es_models.Event) error {
o.LabelPolicy = new(iam_es_model.LabelPolicy)
err := o.LabelPolicy.SetDataLabel(event)
if err != nil {
return err
}
o.LabelPolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (o *Org) appendChangeLabelPolicyEvent(event *es_models.Event) error {
return o.LabelPolicy.SetDataLabel(event)
}
func (o *Org) appendRemoveLabelPolicyEvent(event *es_models.Event) {
o.LabelPolicy = nil
}

View File

@@ -0,0 +1,91 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/models"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
)
func TestAppendAddLabelPolicyEvent(t *testing.T) {
type args struct {
org *Org
policy *iam_es_model.LabelPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *Org
}{
{
name: "append add label policy event",
args: args{
org: &Org{},
policy: &iam_es_model.LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"},
event: &es_models.Event{},
},
result: &Org{LabelPolicy: &iam_es_model.LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.org.appendAddLabelPolicyEvent(tt.args.event)
if tt.result.LabelPolicy.PrimaryColor != tt.args.org.LabelPolicy.PrimaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.LabelPolicy.PrimaryColor, tt.args.org.LabelPolicy.PrimaryColor)
}
if tt.result.LabelPolicy.SecondaryColor != tt.args.org.LabelPolicy.SecondaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.LabelPolicy.SecondaryColor, tt.args.org.LabelPolicy.SecondaryColor)
}
})
}
}
func TestAppendChangeLabelPolicyEvent(t *testing.T) {
type args struct {
org *Org
policy *iam_es_model.LabelPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *Org
}{
{
name: "append change label policy event",
args: args{
org: &Org{LabelPolicy: &iam_es_model.LabelPolicy{
SecondaryColor: "FFFFF0",
PrimaryColor: "000001",
}},
policy: &iam_es_model.LabelPolicy{PrimaryColor: "000000", SecondaryColor: "FFFFFF"},
event: &es_models.Event{},
},
result: &Org{LabelPolicy: &iam_es_model.LabelPolicy{
SecondaryColor: "FFFFFF",
PrimaryColor: "000000",
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.org.appendChangeLabelPolicyEvent(tt.args.event)
if tt.result.LabelPolicy.PrimaryColor != tt.args.org.LabelPolicy.PrimaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.LabelPolicy.PrimaryColor, tt.args.org.LabelPolicy.PrimaryColor)
}
if tt.result.LabelPolicy.SecondaryColor != tt.args.org.LabelPolicy.SecondaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.LabelPolicy.SecondaryColor, tt.args.org.LabelPolicy.SecondaryColor)
}
})
}
}

View File

@@ -2,6 +2,7 @@ package model
import (
"encoding/json"
"github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
@@ -23,6 +24,7 @@ type Org struct {
Domains []*OrgDomain `json:"-"`
Members []*OrgMember `json:"-"`
OrgIAMPolicy *iam_es_model.OrgIAMPolicy `json:"-"`
LabelPolicy *iam_es_model.LabelPolicy `json:"-"`
IDPs []*iam_es_model.IDPConfig `json:"-"`
LoginPolicy *iam_es_model.LoginPolicy `json:"-"`
PasswordComplexityPolicy *iam_es_model.PasswordComplexityPolicy `json:"-"`
@@ -48,6 +50,9 @@ func OrgFromModel(org *org_model.Org) *Org {
if org.LoginPolicy != nil {
converted.LoginPolicy = iam_es_model.LoginPolicyFromModel(org.LoginPolicy)
}
if org.LabelPolicy != nil {
converted.LabelPolicy = iam_es_model.LabelPolicyFromModel(org.LabelPolicy)
}
if org.PasswordComplexityPolicy != nil {
converted.PasswordComplexityPolicy = iam_es_model.PasswordComplexityPolicyFromModel(org.PasswordComplexityPolicy)
}
@@ -75,6 +80,9 @@ func OrgToModel(org *Org) *org_model.Org {
if org.LoginPolicy != nil {
converted.LoginPolicy = iam_es_model.LoginPolicyToModel(org.LoginPolicy)
}
if org.LabelPolicy != nil {
converted.LabelPolicy = iam_es_model.LabelPolicyToModel(org.LabelPolicy)
}
if org.PasswordComplexityPolicy != nil {
converted.PasswordComplexityPolicy = iam_es_model.PasswordComplexityPolicyToModel(org.PasswordComplexityPolicy)
}
@@ -175,6 +183,12 @@ func (o *Org) AppendEvent(event *es_models.Event) (err error) {
err = o.appendAddOIDCIDPConfigEvent(event)
case OIDCIDPConfigChanged:
err = o.appendChangeOIDCIDPConfigEvent(event)
case LabelPolicyAdded:
err = o.appendAddLabelPolicyEvent(event)
case LabelPolicyChanged:
err = o.appendChangeLabelPolicyEvent(event)
case LabelPolicyRemoved:
o.appendRemoveLabelPolicyEvent(event)
case LoginPolicyAdded:
err = o.appendAddLoginPolicyEvent(event)
case LoginPolicyChanged:

View File

@@ -51,6 +51,9 @@ const (
LoginPolicyIDPProviderAdded models.EventType = "org.policy.login.idpprovider.added"
LoginPolicyIDPProviderRemoved models.EventType = "org.policy.login.idpprovider.removed"
LoginPolicyIDPProviderCascadeRemoved models.EventType = "org.policy.login.idpprovider.cascade.removed"
LabelPolicyAdded models.EventType = "org.policy.label.added"
LabelPolicyChanged models.EventType = "org.policy.label.changed"
LabelPolicyRemoved models.EventType = "org.policy.label.removed"
PasswordComplexityPolicyAdded models.EventType = "org.policy.password.complexity.added"
PasswordComplexityPolicyChanged models.EventType = "org.policy.password.complexity.changed"

View File

@@ -11,6 +11,7 @@ type IAMSetUp struct {
Step3 *Step3
Step4 *Step4
Step5 *Step5
Step6 *Step6
}
func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) {
@@ -23,6 +24,7 @@ func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) {
setup.Step3,
setup.Step4,
setup.Step5,
setup.Step6,
} {
if step.step() <= currentDone {
continue

58
internal/setup/step6.go Normal file
View File

@@ -0,0 +1,58 @@
package setup
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
)
type Step6 struct {
DefaultLabelPolicy iam_model.LabelPolicy
setup *Setup
}
func (s *Step6) isNil() bool {
return s == nil
}
func (step *Step6) step() iam_model.Step {
return iam_model.Step6
}
func (step *Step6) init(setup *Setup) {
step.setup = setup
}
func (step *Step6) execute(ctx context.Context) (*iam_model.IAM, error) {
iam, agg, err := step.labelPolicy(ctx, &step.DefaultLabelPolicy)
if err != nil {
logging.Log("SETUP-ZTuS1").WithField("step", step.step()).WithError(err).Error("unable to finish setup (Label policy)")
return nil, err
}
iam, agg, push, err := step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step())
if err != nil {
logging.Log("SETUP-OkF8o").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)")
return nil, err
}
err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg)
if err != nil {
logging.Log("SETUP-YbQ6T").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}
func (step *Step6) labelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_es_model.IAM, *models.Aggregate, error) {
logging.Log("SETUP-geMuZ").Info("setting up labelpolicy")
policy.AggregateID = step.setup.iamID
iam, aggregate, err := step.setup.IamEvents.PrepareAddLabelPolicy(ctx, policy)
if err != nil {
return nil, nil, err
}
return iam, aggregate, nil
}