mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-13 17:35:12 +00:00
feat: limit amount of active actions (#3143)
* max actions * fix: max allowed actions * fix: max allowed actions * fix tests
This commit is contained in:
@@ -31,7 +31,8 @@ type FeaturesWriteModel struct {
|
||||
CustomTextMessage bool
|
||||
CustomTextLogin bool
|
||||
LockoutPolicy bool
|
||||
Actions bool
|
||||
ActionsAllowed domain.ActionsAllowed
|
||||
MaxActions int
|
||||
}
|
||||
|
||||
func (wm *FeaturesWriteModel) Reduce() error {
|
||||
@@ -103,7 +104,16 @@ func (wm *FeaturesWriteModel) Reduce() error {
|
||||
wm.LockoutPolicy = *e.LockoutPolicy
|
||||
}
|
||||
if e.Actions != nil {
|
||||
wm.Actions = *e.Actions
|
||||
wm.ActionsAllowed = domain.ActionsNotAllowed
|
||||
if *e.Actions {
|
||||
wm.ActionsAllowed = domain.ActionsAllowedUnlimited
|
||||
}
|
||||
}
|
||||
if e.ActionsAllowed != nil {
|
||||
wm.ActionsAllowed = *e.ActionsAllowed
|
||||
}
|
||||
if e.MaxActions != nil {
|
||||
wm.MaxActions = *e.MaxActions
|
||||
}
|
||||
case *features.FeaturesRemovedEvent:
|
||||
wm.State = domain.FeaturesStateRemoved
|
||||
|
||||
@@ -195,6 +195,7 @@ func writeModelToFeatures(wm *FeaturesWriteModel) *domain.Features {
|
||||
CustomTextMessage: wm.CustomTextMessage,
|
||||
CustomTextLogin: wm.CustomTextLogin,
|
||||
LockoutPolicy: wm.LockoutPolicy,
|
||||
Actions: wm.Actions,
|
||||
ActionsAllowed: wm.ActionsAllowed,
|
||||
MaxActions: wm.MaxActions,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,8 @@ func (c *Commands) setDefaultFeatures(ctx context.Context, existingFeatures *IAM
|
||||
features.CustomTextMessage,
|
||||
features.CustomTextLogin,
|
||||
features.LockoutPolicy,
|
||||
features.Actions,
|
||||
features.ActionsAllowed,
|
||||
features.MaxActions,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||
|
||||
@@ -72,8 +72,9 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin,
|
||||
lockoutPolicy,
|
||||
actions bool,
|
||||
lockoutPolicy bool,
|
||||
actionsAllowed domain.ActionsAllowed,
|
||||
maxActions int,
|
||||
) (*iam.FeaturesSetEvent, bool) {
|
||||
|
||||
changes := make([]features.FeaturesChanges, 0)
|
||||
@@ -138,8 +139,11 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
||||
if wm.LockoutPolicy != lockoutPolicy {
|
||||
changes = append(changes, features.ChangeLockoutPolicy(lockoutPolicy))
|
||||
}
|
||||
if wm.Actions != actions {
|
||||
changes = append(changes, features.ChangeActions(actions))
|
||||
if wm.ActionsAllowed != actionsAllowed {
|
||||
changes = append(changes, features.ChangeActionsAllowed(actionsAllowed))
|
||||
}
|
||||
if wm.MaxActions != maxActions {
|
||||
changes = append(changes, features.ChangeMaxActions(maxActions))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
|
||||
@@ -2,6 +2,7 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
@@ -14,6 +15,10 @@ func (c *Commands) AddAction(ctx context.Context, addAction *domain.Action, reso
|
||||
if !addAction.IsValid() {
|
||||
return "", nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-eg2gf", "Errors.Action.Invalid")
|
||||
}
|
||||
err = c.checkAdditionalActionAllowed(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
addAction.AggregateID, err = c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
@@ -39,6 +44,27 @@ func (c *Commands) AddAction(ctx context.Context, addAction *domain.Action, reso
|
||||
return actionModel.AggregateID, writeModelToObjectDetails(&actionModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkAdditionalActionAllowed(ctx context.Context, resourceOwner string) error {
|
||||
features, err := c.getOrgFeaturesOrDefault(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingActions, err := c.getActionsByOrgWriteModelByID(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
activeActions := make([]*ActionWriteModel, 0, len(existingActions.Actions))
|
||||
for _, existingAction := range existingActions.Actions {
|
||||
if existingAction.State == domain.ActionStateActive {
|
||||
activeActions = append(activeActions, existingAction)
|
||||
}
|
||||
}
|
||||
if len(activeActions) < features.MaxActions {
|
||||
return nil
|
||||
}
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-dfwg2", "Errors.Action.MaxAllowed")
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeAction(ctx context.Context, actionChange *domain.Action, resourceOwner string) (*domain.ObjectDetails, error) {
|
||||
if !actionChange.IsValid() || actionChange.AggregateID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-Df2f3", "Errors.Action.Invalid")
|
||||
@@ -119,6 +145,11 @@ func (c *Commands) ReactivateAction(ctx context.Context, actionID string, resour
|
||||
if existingAction.State != domain.ActionStateInactive {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-J53zh", "Errors.Action.NotInactive")
|
||||
}
|
||||
err = c.checkAdditionalActionAllowed(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
actionAgg := ActionAggregateFromWriteModel(&existingAction.WriteModel)
|
||||
events := []eventstore.Command{
|
||||
action.NewReactivatedEvent(ctx, actionAgg),
|
||||
@@ -174,9 +205,34 @@ func (c *Commands) removeActionsFromOrg(ctx context.Context, resourceOwner strin
|
||||
return nil, nil
|
||||
}
|
||||
events := make([]eventstore.Command, 0, len(existingActions.Actions))
|
||||
for id, name := range existingActions.Actions {
|
||||
for id, existingAction := range existingActions.Actions {
|
||||
actionAgg := NewActionAggregate(id, resourceOwner)
|
||||
events = append(events, action.NewRemovedEvent(ctx, actionAgg, name))
|
||||
events = append(events, action.NewRemovedEvent(ctx, actionAgg, existingAction.Name))
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (c *Commands) deactivateNotAllowedActionsFromOrg(ctx context.Context, resourceOwner string, maxAllowed int) ([]eventstore.Command, error) {
|
||||
existingActions, err := c.getActionsByOrgWriteModelByID(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
activeActions := make([]*ActionWriteModel, 0, len(existingActions.Actions))
|
||||
for _, existingAction := range existingActions.Actions {
|
||||
if existingAction.State == domain.ActionStateActive {
|
||||
activeActions = append(activeActions, existingAction)
|
||||
}
|
||||
}
|
||||
if len(activeActions) <= maxAllowed {
|
||||
return nil, nil
|
||||
}
|
||||
sort.Slice(activeActions, func(i, j int) bool {
|
||||
return activeActions[i].WriteModel.ChangeDate.Before(activeActions[j].WriteModel.ChangeDate)
|
||||
})
|
||||
events := make([]eventstore.Command, 0, len(existingActions.Actions))
|
||||
for i := maxAllowed; i < len(activeActions); i++ {
|
||||
actionAgg := NewActionAggregate(activeActions[i].AggregateID, resourceOwner)
|
||||
events = append(events, action.NewDeactivatedEvent(ctx, actionAgg))
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ func (wm *ActionExistsModel) Query() *eventstore.SearchQueryBuilder {
|
||||
type ActionsListByOrgModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Actions map[string]string
|
||||
Actions map[string]*ActionWriteModel
|
||||
}
|
||||
|
||||
func NewActionsListByOrgModel(resourceOwner string) *ActionsListByOrgModel {
|
||||
@@ -167,7 +167,7 @@ func NewActionsListByOrgModel(resourceOwner string) *ActionsListByOrgModel {
|
||||
WriteModel: eventstore.WriteModel{
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
Actions: make(map[string]string),
|
||||
Actions: make(map[string]*ActionWriteModel),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,18 @@ func (wm *ActionsListByOrgModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *action.AddedEvent:
|
||||
wm.Actions[e.Aggregate().ID] = e.Name
|
||||
wm.Actions[e.Aggregate().ID] = &ActionWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: e.Aggregate().ID,
|
||||
ChangeDate: e.CreationDate(),
|
||||
},
|
||||
Name: e.Name,
|
||||
State: domain.ActionStateActive,
|
||||
}
|
||||
case *action.DeactivatedEvent:
|
||||
wm.Actions[e.Aggregate().ID].State = domain.ActionStateInactive
|
||||
case *action.ReactivatedEvent:
|
||||
wm.Actions[e.Aggregate().ID].State = domain.ActionStateActive
|
||||
case *action.RemovedEvent:
|
||||
delete(wm.Actions, e.Aggregate().ID)
|
||||
}
|
||||
@@ -189,6 +200,8 @@ func (wm *ActionsListByOrgModel) Query() *eventstore.SearchQueryBuilder {
|
||||
AddQuery().
|
||||
AggregateTypes(action.AggregateType).
|
||||
EventTypes(action.AddedEventType,
|
||||
action.DeactivatedEventType,
|
||||
action.ReactivatedEventType,
|
||||
action.RemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/caos/zitadel/internal/repository/features"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
@@ -13,7 +17,6 @@ import (
|
||||
"github.com/caos/zitadel/internal/id/mock"
|
||||
"github.com/caos/zitadel/internal/repository/action"
|
||||
"github.com/caos/zitadel/internal/repository/org"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCommands_AddAction(t *testing.T) {
|
||||
@@ -53,10 +56,76 @@ func TestCommands_AddAction(t *testing.T) {
|
||||
err: errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"no additional allowed, error",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewFeaturesSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
[]features.FeaturesChanges{
|
||||
features.ChangeMaxActions(1),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
"name",
|
||||
"name() {};",
|
||||
0,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
addAction: &domain.Action{
|
||||
Name: "name",
|
||||
Script: "name() {};",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res{
|
||||
err: errors.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
"unique constraint failed, error",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewFeaturesSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
[]features.FeaturesChanges{
|
||||
features.ChangeMaxActions(2),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
"name",
|
||||
"name() {};",
|
||||
0,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPushFailed(
|
||||
errors.ThrowPreconditionFailed(nil, "id", "name already exists"),
|
||||
[]*repository.Event{
|
||||
@@ -91,33 +160,57 @@ func TestCommands_AddAction(t *testing.T) {
|
||||
"push ok",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewFeaturesSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
[]features.FeaturesChanges{
|
||||
features.ChangeMaxActions(2),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
"name",
|
||||
"name() {};",
|
||||
0,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
"name",
|
||||
"name() {};",
|
||||
&action.NewAggregate("id2", "org1").Aggregate,
|
||||
"name2",
|
||||
"name2() {};",
|
||||
0,
|
||||
false,
|
||||
),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(action.NewAddActionNameUniqueConstraint("name", "org1")),
|
||||
uniqueConstraintsFromEventConstraint(action.NewAddActionNameUniqueConstraint("name2", "org1")),
|
||||
),
|
||||
),
|
||||
idGenerator: mock.ExpectID(t, "id1"),
|
||||
idGenerator: mock.ExpectID(t, "id2"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
addAction: &domain.Action{
|
||||
Name: "name",
|
||||
Script: "name() {};",
|
||||
Name: "name2",
|
||||
Script: "name2() {};",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res{
|
||||
id: "id1",
|
||||
id: "id2",
|
||||
details: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
@@ -570,10 +663,94 @@ func TestCommands_ReactivateAction(t *testing.T) {
|
||||
err: errors.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
"no additional allowed, error",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
"name",
|
||||
"name() {};",
|
||||
0,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
action.NewDeactivatedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewFeaturesSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
[]features.FeaturesChanges{
|
||||
features.ChangeMaxActions(1),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
&action.NewAggregate("id2", "org1").Aggregate,
|
||||
"name2",
|
||||
"name2() {};",
|
||||
0,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
actionID: "id1",
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res{
|
||||
err: errors.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
"reactivate ok",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
"name",
|
||||
"name() {};",
|
||||
0,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
action.NewDeactivatedEvent(context.Background(),
|
||||
&action.NewAggregate("id1", "org1").Aggregate,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewFeaturesSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
[]features.FeaturesChanges{
|
||||
features.ChangeMaxActions(1),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
|
||||
@@ -45,7 +45,8 @@ func (c *Commands) SetOrgFeatures(ctx context.Context, resourceOwner string, fea
|
||||
features.CustomTextMessage,
|
||||
features.CustomTextLogin,
|
||||
features.LockoutPolicy,
|
||||
features.Actions,
|
||||
features.ActionsAllowed,
|
||||
features.MaxActions,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||
@@ -177,7 +178,7 @@ func (c *Commands) ensureOrgSettingsToFeatures(ctx context.Context, orgID string
|
||||
events = append(events, removeOrgUserMetadatas...)
|
||||
}
|
||||
}
|
||||
if !features.Actions {
|
||||
if features.ActionsAllowed == domain.ActionsNotAllowed {
|
||||
removeOrgActions, err := c.removeActionsFromOrg(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -186,6 +187,15 @@ func (c *Commands) ensureOrgSettingsToFeatures(ctx context.Context, orgID string
|
||||
events = append(events, removeOrgActions...)
|
||||
}
|
||||
}
|
||||
if features.ActionsAllowed == domain.ActionsMaxAllowed {
|
||||
deactivateActions, err := c.deactivateNotAllowedActionsFromOrg(ctx, orgID, features.MaxActions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(deactivateActions) > 0 {
|
||||
events = append(events, deactivateActions...)
|
||||
}
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
@@ -351,3 +361,21 @@ func (c *Commands) setAllowedLabelPolicy(ctx context.Context, orgID string, feat
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (c *Commands) getOrgFeaturesOrDefault(ctx context.Context, orgID string) (*domain.Features, error) {
|
||||
existingFeatures := NewOrgFeaturesWriteModel(orgID)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingFeatures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingFeatures.State != domain.FeaturesStateUnspecified && existingFeatures.State != domain.FeaturesStateRemoved {
|
||||
return writeModelToFeatures(&existingFeatures.FeaturesWriteModel), nil
|
||||
}
|
||||
|
||||
existingIAMFeatures := NewIAMFeaturesWriteModel()
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, existingIAMFeatures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToFeatures(&existingIAMFeatures.FeaturesWriteModel), nil
|
||||
}
|
||||
|
||||
@@ -78,8 +78,9 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin,
|
||||
lockoutPolicy,
|
||||
actions bool,
|
||||
lockoutPolicy bool,
|
||||
actionsAllowed domain.ActionsAllowed,
|
||||
maxActions int,
|
||||
) (*org.FeaturesSetEvent, bool) {
|
||||
|
||||
changes := make([]features.FeaturesChanges, 0)
|
||||
@@ -144,8 +145,11 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
|
||||
if wm.LockoutPolicy != lockoutPolicy {
|
||||
changes = append(changes, features.ChangeLockoutPolicy(lockoutPolicy))
|
||||
}
|
||||
if wm.Actions != actions {
|
||||
changes = append(changes, features.ChangeActions(actions))
|
||||
if wm.ActionsAllowed != actionsAllowed {
|
||||
changes = append(changes, features.ChangeActionsAllowed(actionsAllowed))
|
||||
}
|
||||
if wm.MaxActions != maxActions {
|
||||
changes = append(changes, features.ChangeMaxActions(maxActions))
|
||||
}
|
||||
|
||||
if len(changes) == 0 {
|
||||
|
||||
@@ -308,7 +308,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
PrivacyPolicy: false,
|
||||
MetadataUser: false,
|
||||
LockoutPolicy: false,
|
||||
Actions: false,
|
||||
ActionsAllowed: domain.ActionsNotAllowed,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -512,7 +512,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
Actions: false,
|
||||
ActionsAllowed: domain.ActionsNotAllowed,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -726,7 +726,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
Actions: false,
|
||||
ActionsAllowed: domain.ActionsNotAllowed,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -950,7 +950,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
Actions: false,
|
||||
ActionsAllowed: domain.ActionsNotAllowed,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -1243,7 +1243,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
Actions: false,
|
||||
ActionsAllowed: domain.ActionsNotAllowed,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -1433,7 +1433,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
PrivacyPolicy: false,
|
||||
MetadataUser: false,
|
||||
LockoutPolicy: false,
|
||||
Actions: false,
|
||||
ActionsAllowed: domain.ActionsNotAllowed,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
|
||||
Reference in New Issue
Block a user