zitadel/internal/command/org_action.go
Livio Amstutz a7816a43b1
refactor: remove commandNew struct (#3465)
* refactor: remove commandNew struct

* requested fixes
2022-04-20 14:59:37 +00:00

257 lines
8.7 KiB
Go

package command
import (
"context"
"sort"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/repository/action"
"github.com/caos/zitadel/internal/repository/org"
)
func (c *Commands) AddAction(ctx context.Context, addAction *domain.Action, resourceOwner string) (_ string, _ *domain.ObjectDetails, err error) {
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
}
actionModel := NewActionWriteModel(addAction.AggregateID, resourceOwner)
actionAgg := ActionAggregateFromWriteModel(&actionModel.WriteModel)
pushedEvents, err := c.eventstore.Push(ctx, action.NewAddedEvent(
ctx,
actionAgg,
addAction.Name,
addAction.Script,
addAction.Timeout,
addAction.AllowedToFail,
))
if err != nil {
return "", nil, err
}
err = AppendAndReduce(actionModel, pushedEvents...)
if err != nil {
return "", nil, err
}
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 features.ActionsAllowed == domain.ActionsAllowedUnlimited || 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")
}
existingAction, err := c.getActionWriteModelByID(ctx, actionChange.AggregateID, resourceOwner)
if err != nil {
return nil, err
}
if !existingAction.State.Exists() {
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-Sfg2t", "Errors.Action.NotFound")
}
actionAgg := ActionAggregateFromWriteModel(&existingAction.WriteModel)
changedEvent, err := existingAction.NewChangedEvent(
ctx,
actionAgg,
actionChange.Name,
actionChange.Script,
actionChange.Timeout,
actionChange.AllowedToFail)
if err != nil {
return nil, err
}
pushedEvents, err := c.eventstore.Push(ctx, changedEvent)
if err != nil {
return nil, err
}
err = AppendAndReduce(existingAction, pushedEvents...)
if err != nil {
return nil, err
}
return writeModelToObjectDetails(&existingAction.WriteModel), nil
}
func (c *Commands) DeactivateAction(ctx context.Context, actionID string, resourceOwner string) (*domain.ObjectDetails, error) {
if actionID == "" || resourceOwner == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-DAhk5", "Errors.IDMissing")
}
existingAction, err := c.getActionWriteModelByID(ctx, actionID, resourceOwner)
if err != nil {
return nil, err
}
if !existingAction.State.Exists() {
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-NRmhu", "Errors.Action.NotFound")
}
if existingAction.State != domain.ActionStateActive {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Dgj92", "Errors.Action.NotActive")
}
actionAgg := ActionAggregateFromWriteModel(&existingAction.WriteModel)
events := []eventstore.Command{
action.NewDeactivatedEvent(ctx, actionAgg),
}
pushedEvents, err := c.eventstore.Push(ctx, events...)
if err != nil {
return nil, err
}
err = AppendAndReduce(existingAction, pushedEvents...)
if err != nil {
return nil, err
}
return writeModelToObjectDetails(&existingAction.WriteModel), nil
}
func (c *Commands) ReactivateAction(ctx context.Context, actionID string, resourceOwner string) (*domain.ObjectDetails, error) {
if actionID == "" || resourceOwner == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-BNm56", "Errors.IDMissing")
}
existingAction, err := c.getActionWriteModelByID(ctx, actionID, resourceOwner)
if err != nil {
return nil, err
}
if !existingAction.State.Exists() {
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-Aa22g", "Errors.Action.NotFound")
}
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),
}
pushedEvents, err := c.eventstore.Push(ctx, events...)
if err != nil {
return nil, err
}
err = AppendAndReduce(existingAction, pushedEvents...)
if err != nil {
return nil, err
}
return writeModelToObjectDetails(&existingAction.WriteModel), nil
}
func (c *Commands) DeleteAction(ctx context.Context, actionID, resourceOwner string, flowTypes ...domain.FlowType) (*domain.ObjectDetails, error) {
if actionID == "" || resourceOwner == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-Gfg3g", "Errors.IDMissing")
}
existingAction, err := c.getActionWriteModelByID(ctx, actionID, resourceOwner)
if err != nil {
return nil, err
}
if !existingAction.State.Exists() {
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-Dgh4h", "Errors.Action.NotFound")
}
actionAgg := ActionAggregateFromWriteModel(&existingAction.WriteModel)
events := []eventstore.Command{
action.NewRemovedEvent(ctx, actionAgg, existingAction.Name),
}
orgAgg := org.NewAggregate(resourceOwner).Aggregate
for _, flowType := range flowTypes {
events = append(events, org.NewTriggerActionsCascadeRemovedEvent(ctx, &orgAgg, flowType, actionID))
}
pushedEvents, err := c.eventstore.Push(ctx, events...)
if err != nil {
return nil, err
}
err = AppendAndReduce(existingAction, pushedEvents...)
if err != nil {
return nil, err
}
return writeModelToObjectDetails(&existingAction.WriteModel), nil
}
func (c *Commands) removeActionsFromOrg(ctx context.Context, resourceOwner string) ([]eventstore.Command, error) {
existingActions, err := c.getActionsByOrgWriteModelByID(ctx, resourceOwner)
if err != nil {
return nil, err
}
if len(existingActions.Actions) == 0 {
return nil, nil
}
events := make([]eventstore.Command, 0, len(existingActions.Actions))
for id, existingAction := range existingActions.Actions {
actionAgg := NewActionAggregate(id, resourceOwner)
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
}
func (c *Commands) getActionWriteModelByID(ctx context.Context, actionID string, resourceOwner string) (*ActionWriteModel, error) {
actionWriteModel := NewActionWriteModel(actionID, resourceOwner)
err := c.eventstore.FilterToQueryReducer(ctx, actionWriteModel)
if err != nil {
return nil, err
}
return actionWriteModel, nil
}
func (c *Commands) getActionsByOrgWriteModelByID(ctx context.Context, resourceOwner string) (*ActionsListByOrgModel, error) {
actionWriteModel := NewActionsListByOrgModel(resourceOwner)
err := c.eventstore.FilterToQueryReducer(ctx, actionWriteModel)
if err != nil {
return nil, err
}
return actionWriteModel, nil
}