mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:57:33 +00:00
feat: permit all features to every instance and organisation (#3566)
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
authz_repo "github.com/zitadel/zitadel/internal/authz/repository"
|
||||
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
@@ -50,19 +48,12 @@ type Commands struct {
|
||||
keyAlgorithm crypto.EncryptionAlgorithm
|
||||
privateKeyLifetime time.Duration
|
||||
publicKeyLifetime time.Duration
|
||||
|
||||
tokenVerifier orgFeatureChecker
|
||||
}
|
||||
|
||||
type orgFeatureChecker interface {
|
||||
CheckOrgFeatures(ctx context.Context, orgID string, requiredFeatures ...string) error
|
||||
}
|
||||
|
||||
func StartCommands(es *eventstore.Eventstore,
|
||||
defaults sd.SystemDefaults,
|
||||
zitadelRoles []authz.RoleMapping,
|
||||
staticStore static.Storage,
|
||||
authZRepo authz_repo.Repository,
|
||||
webAuthN *webauthn_helper.Config,
|
||||
externalDomain string,
|
||||
externalSecure bool,
|
||||
@@ -119,8 +110,6 @@ func StartCommands(es *eventstore.Eventstore,
|
||||
|
||||
repo.domainVerificationGenerator = crypto.NewEncryptionGenerator(defaults.DomainVerification.VerificationGenerator, repo.domainVerificationAlg)
|
||||
repo.domainVerificationValidator = http.ValidateDomain
|
||||
|
||||
repo.tokenVerifier = authZRepo
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
|
@@ -1,123 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/features"
|
||||
)
|
||||
|
||||
type FeaturesWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
TierName string
|
||||
TierDescription string
|
||||
State domain.FeaturesState
|
||||
StateDescription string
|
||||
AuditLogRetention time.Duration
|
||||
LoginPolicyFactors bool
|
||||
LoginPolicyIDP bool
|
||||
LoginPolicyPasswordless bool
|
||||
LoginPolicyRegistration bool
|
||||
LoginPolicyUsernameLogin bool
|
||||
LoginPolicyPasswordReset bool
|
||||
PasswordComplexityPolicy bool
|
||||
LabelPolicyPrivateLabel bool
|
||||
LabelPolicyWatermark bool
|
||||
CustomDomain bool
|
||||
PrivacyPolicy bool
|
||||
MetadataUser bool
|
||||
CustomTextMessage bool
|
||||
CustomTextLogin bool
|
||||
LockoutPolicy bool
|
||||
ActionsAllowed domain.ActionsAllowed
|
||||
MaxActions int
|
||||
}
|
||||
|
||||
func (wm *FeaturesWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *features.FeaturesSetEvent:
|
||||
if e.TierName != nil {
|
||||
wm.TierName = *e.TierName
|
||||
}
|
||||
if e.TierDescription != nil {
|
||||
wm.TierDescription = *e.TierDescription
|
||||
}
|
||||
wm.State = domain.FeaturesStateActive
|
||||
if e.State != nil {
|
||||
wm.State = *e.State
|
||||
}
|
||||
if e.StateDescription != nil {
|
||||
wm.StateDescription = *e.StateDescription
|
||||
}
|
||||
if e.AuditLogRetention != nil {
|
||||
wm.AuditLogRetention = *e.AuditLogRetention
|
||||
}
|
||||
if e.LoginPolicyFactors != nil {
|
||||
wm.LoginPolicyFactors = *e.LoginPolicyFactors
|
||||
}
|
||||
if e.LoginPolicyIDP != nil {
|
||||
wm.LoginPolicyIDP = *e.LoginPolicyIDP
|
||||
}
|
||||
if e.LoginPolicyPasswordless != nil {
|
||||
wm.LoginPolicyPasswordless = *e.LoginPolicyPasswordless
|
||||
}
|
||||
if e.LoginPolicyRegistration != nil {
|
||||
wm.LoginPolicyRegistration = *e.LoginPolicyRegistration
|
||||
}
|
||||
if e.LoginPolicyUsernameLogin != nil {
|
||||
wm.LoginPolicyUsernameLogin = *e.LoginPolicyUsernameLogin
|
||||
}
|
||||
if e.LoginPolicyPasswordReset != nil {
|
||||
wm.LoginPolicyPasswordReset = *e.LoginPolicyPasswordReset
|
||||
}
|
||||
if e.PasswordComplexityPolicy != nil {
|
||||
wm.PasswordComplexityPolicy = *e.PasswordComplexityPolicy
|
||||
}
|
||||
if e.LabelPolicy != nil {
|
||||
wm.LabelPolicyPrivateLabel = *e.LabelPolicy
|
||||
}
|
||||
if e.LabelPolicyPrivateLabel != nil {
|
||||
wm.LabelPolicyPrivateLabel = *e.LabelPolicyPrivateLabel
|
||||
}
|
||||
if e.LabelPolicyWatermark != nil {
|
||||
wm.LabelPolicyWatermark = *e.LabelPolicyWatermark
|
||||
}
|
||||
if e.CustomDomain != nil {
|
||||
wm.CustomDomain = *e.CustomDomain
|
||||
}
|
||||
if e.PrivacyPolicy != nil {
|
||||
wm.PrivacyPolicy = *e.PrivacyPolicy
|
||||
}
|
||||
if e.MetadataUser != nil {
|
||||
wm.MetadataUser = *e.MetadataUser
|
||||
}
|
||||
if e.CustomTextMessage != nil {
|
||||
wm.CustomTextMessage = *e.CustomTextMessage
|
||||
}
|
||||
if e.CustomTextLogin != nil {
|
||||
wm.CustomTextLogin = *e.CustomTextLogin
|
||||
}
|
||||
if e.LockoutPolicy != nil {
|
||||
wm.LockoutPolicy = *e.LockoutPolicy
|
||||
}
|
||||
if e.Actions != nil {
|
||||
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
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -29,34 +29,10 @@ const (
|
||||
)
|
||||
|
||||
type InstanceSetup struct {
|
||||
zitadel ZitadelConfig
|
||||
InstanceName string
|
||||
CustomDomain string
|
||||
Org OrgSetup
|
||||
Features struct {
|
||||
TierName string
|
||||
TierDescription string
|
||||
Retention time.Duration
|
||||
State domain.FeaturesState
|
||||
StateDescription string
|
||||
LoginPolicyFactors bool
|
||||
LoginPolicyIDP bool
|
||||
LoginPolicyPasswordless bool
|
||||
LoginPolicyRegistration bool
|
||||
LoginPolicyUsernameLogin bool
|
||||
LoginPolicyPasswordReset bool
|
||||
PasswordComplexityPolicy bool
|
||||
LabelPolicyPrivateLabel bool
|
||||
LabelPolicyWatermark bool
|
||||
CustomDomain bool
|
||||
PrivacyPolicy bool
|
||||
MetadataUser bool
|
||||
CustomTextMessage bool
|
||||
CustomTextLogin bool
|
||||
LockoutPolicy bool
|
||||
ActionsAllowed domain.ActionsAllowed
|
||||
MaxActions int
|
||||
}
|
||||
zitadel ZitadelConfig
|
||||
InstanceName string
|
||||
CustomDomain string
|
||||
Org OrgSetup
|
||||
SecretGenerators struct {
|
||||
PasswordSaltCost uint
|
||||
ClientSecret *crypto.GeneratorConfig
|
||||
@@ -191,31 +167,6 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
|
||||
validations := []preparation.Validation{
|
||||
addInstance(instanceAgg, setup.InstanceName),
|
||||
SetDefaultFeatures(
|
||||
instanceAgg,
|
||||
setup.Features.TierName,
|
||||
setup.Features.TierDescription,
|
||||
setup.Features.State,
|
||||
setup.Features.StateDescription,
|
||||
setup.Features.Retention,
|
||||
setup.Features.LoginPolicyFactors,
|
||||
setup.Features.LoginPolicyIDP,
|
||||
setup.Features.LoginPolicyPasswordless,
|
||||
setup.Features.LoginPolicyRegistration,
|
||||
setup.Features.LoginPolicyUsernameLogin,
|
||||
setup.Features.LoginPolicyPasswordReset,
|
||||
setup.Features.PasswordComplexityPolicy,
|
||||
setup.Features.LabelPolicyPrivateLabel,
|
||||
setup.Features.LabelPolicyWatermark,
|
||||
setup.Features.CustomDomain,
|
||||
setup.Features.PrivacyPolicy,
|
||||
setup.Features.MetadataUser,
|
||||
setup.Features.CustomTextMessage,
|
||||
setup.Features.CustomTextLogin,
|
||||
setup.Features.LockoutPolicy,
|
||||
setup.Features.ActionsAllowed,
|
||||
setup.Features.MaxActions,
|
||||
),
|
||||
addSecretGeneratorConfig(instanceAgg, domain.SecretGeneratorTypeAppSecret, setup.SecretGenerators.ClientSecret),
|
||||
addSecretGeneratorConfig(instanceAgg, domain.SecretGeneratorTypeInitCode, setup.SecretGenerators.InitializeUserCode),
|
||||
addSecretGeneratorConfig(instanceAgg, domain.SecretGeneratorTypeVerifyEmailCode, setup.SecretGenerators.EmailVerificationCode),
|
||||
|
@@ -169,31 +169,3 @@ func writeModelToIDPProvider(wm *IdentityProviderWriteModel) *domain.IDPProvider
|
||||
Type: wm.IDPProviderType,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToFeatures(wm *FeaturesWriteModel) *domain.Features {
|
||||
return &domain.Features{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
TierName: wm.TierName,
|
||||
TierDescription: wm.TierDescription,
|
||||
State: wm.State,
|
||||
StateDescription: wm.StateDescription,
|
||||
AuditLogRetention: wm.AuditLogRetention,
|
||||
LoginPolicyFactors: wm.LoginPolicyFactors,
|
||||
LoginPolicyIDP: wm.LoginPolicyIDP,
|
||||
LoginPolicyPasswordless: wm.LoginPolicyPasswordless,
|
||||
LoginPolicyRegistration: wm.LoginPolicyRegistration,
|
||||
LoginPolicyUsernameLogin: wm.LoginPolicyUsernameLogin,
|
||||
LoginPolicyPasswordReset: wm.LoginPolicyPasswordReset,
|
||||
PasswordComplexityPolicy: wm.PasswordComplexityPolicy,
|
||||
LabelPolicyPrivateLabel: wm.LabelPolicyPrivateLabel,
|
||||
LabelPolicyWatermark: wm.LabelPolicyWatermark,
|
||||
CustomDomain: wm.CustomDomain,
|
||||
PrivacyPolicy: wm.PrivacyPolicy,
|
||||
MetadataUser: wm.MetadataUser,
|
||||
CustomTextMessage: wm.CustomTextMessage,
|
||||
CustomTextLogin: wm.CustomTextLogin,
|
||||
LockoutPolicy: wm.LockoutPolicy,
|
||||
ActionsAllowed: wm.ActionsAllowed,
|
||||
MaxActions: wm.MaxActions,
|
||||
}
|
||||
}
|
||||
|
@@ -1,160 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
)
|
||||
|
||||
func SetDefaultFeatures(
|
||||
a *instance.Aggregate,
|
||||
tierName,
|
||||
tierDescription string,
|
||||
state domain.FeaturesState,
|
||||
stateDescription string,
|
||||
retention time.Duration,
|
||||
loginPolicyFactors,
|
||||
loginPolicyIDP,
|
||||
loginPolicyPasswordless,
|
||||
loginPolicyRegistration,
|
||||
loginPolicyUsernameLogin,
|
||||
loginPolicyPasswordReset,
|
||||
passwordComplexityPolicy,
|
||||
labelPolicyPrivateLabel,
|
||||
labelPolicyWatermark,
|
||||
customDomain,
|
||||
privacyPolicy,
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin,
|
||||
lockoutPolicy bool,
|
||||
actionsAllowed domain.ActionsAllowed,
|
||||
maxActions int,
|
||||
) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if !state.Valid() || state == domain.FeaturesStateUnspecified || state == domain.FeaturesStateRemoved {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "INSTA-d3r1s", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel, err := defaultFeatures(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
event, hasChanged := writeModel.NewSetEvent(ctx, &a.Aggregate,
|
||||
tierName,
|
||||
tierDescription,
|
||||
state,
|
||||
stateDescription,
|
||||
retention,
|
||||
loginPolicyFactors,
|
||||
loginPolicyIDP,
|
||||
loginPolicyPasswordless,
|
||||
loginPolicyRegistration,
|
||||
loginPolicyUsernameLogin,
|
||||
loginPolicyPasswordReset,
|
||||
passwordComplexityPolicy,
|
||||
labelPolicyPrivateLabel,
|
||||
labelPolicyWatermark,
|
||||
customDomain,
|
||||
privacyPolicy,
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin,
|
||||
lockoutPolicy,
|
||||
actionsAllowed,
|
||||
maxActions,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "INSTA-GE4h2", "Errors.Features.NotChanged")
|
||||
}
|
||||
return []eventstore.Command{
|
||||
event,
|
||||
}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func defaultFeatures(ctx context.Context, filter preparation.FilterToQueryReducer) (*InstanceFeaturesWriteModel, error) {
|
||||
features := NewInstanceFeaturesWriteModel(ctx)
|
||||
events, err := filter(ctx, features.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(events) == 0 {
|
||||
return features, nil
|
||||
}
|
||||
features.AppendEvents(events...)
|
||||
err = features.Reduce()
|
||||
return features, err
|
||||
}
|
||||
|
||||
func (c *Commands) SetDefaultFeatures(ctx context.Context, features *domain.Features) (*domain.ObjectDetails, error) {
|
||||
existingFeatures := NewInstanceFeaturesWriteModel(ctx)
|
||||
setEvent, err := c.setDefaultFeatures(ctx, existingFeatures, features)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, setEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingFeatures, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&existingFeatures.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) setDefaultFeatures(ctx context.Context, existingFeatures *InstanceFeaturesWriteModel, features *domain.Features) (*instance.FeaturesSetEvent, error) {
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingFeatures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setEvent, hasChanged := existingFeatures.NewSetEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&existingFeatures.FeaturesWriteModel.WriteModel),
|
||||
features.TierName,
|
||||
features.TierDescription,
|
||||
features.State,
|
||||
features.StateDescription,
|
||||
features.AuditLogRetention,
|
||||
features.LoginPolicyFactors,
|
||||
features.LoginPolicyIDP,
|
||||
features.LoginPolicyPasswordless,
|
||||
features.LoginPolicyRegistration,
|
||||
features.LoginPolicyUsernameLogin,
|
||||
features.LoginPolicyPasswordReset,
|
||||
features.PasswordComplexityPolicy,
|
||||
features.LabelPolicyPrivateLabel,
|
||||
features.LabelPolicyWatermark,
|
||||
features.CustomDomain,
|
||||
features.PrivacyPolicy,
|
||||
features.MetadataUser,
|
||||
features.CustomTextMessage,
|
||||
features.CustomTextLogin,
|
||||
features.LockoutPolicy,
|
||||
features.ActionsAllowed,
|
||||
features.MaxActions,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||
}
|
||||
return setEvent, nil
|
||||
}
|
||||
|
||||
func (c *Commands) getDefaultFeatures(ctx context.Context) (*domain.Features, error) {
|
||||
existingFeatures := NewInstanceFeaturesWriteModel(ctx)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingFeatures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
features := writeModelToFeatures(&existingFeatures.FeaturesWriteModel)
|
||||
features.IsDefault = true
|
||||
return features, nil
|
||||
}
|
@@ -1,157 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/features"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
)
|
||||
|
||||
type InstanceFeaturesWriteModel struct {
|
||||
FeaturesWriteModel
|
||||
}
|
||||
|
||||
func NewInstanceFeaturesWriteModel(ctx context.Context) *InstanceFeaturesWriteModel {
|
||||
return &InstanceFeaturesWriteModel{
|
||||
FeaturesWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: authz.GetInstance(ctx).InstanceID(),
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *InstanceFeaturesWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *instance.FeaturesSetEvent:
|
||||
wm.FeaturesWriteModel.AppendEvents(&e.FeaturesSetEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *InstanceFeaturesWriteModel) IsValid() bool {
|
||||
return wm.AggregateID != ""
|
||||
}
|
||||
|
||||
func (wm *InstanceFeaturesWriteModel) Reduce() error {
|
||||
return wm.FeaturesWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *InstanceFeaturesWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
EventTypes(instance.FeaturesSetEventType).
|
||||
AggregateTypes(instance.AggregateType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *InstanceFeaturesWriteModel) NewSetEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
tierName, tierDescription string,
|
||||
state domain.FeaturesState,
|
||||
stateDescription string,
|
||||
auditLogRetention time.Duration,
|
||||
loginPolicyFactors,
|
||||
loginPolicyIDP,
|
||||
loginPolicyPasswordless,
|
||||
loginPolicyRegistration,
|
||||
loginPolicyUsernameLogin,
|
||||
loginPolicyPasswordReset,
|
||||
passwordComplexityPolicy,
|
||||
labelPolicyPrivateLabel,
|
||||
labelPolicyWatermark,
|
||||
customDomain,
|
||||
privacyPolicy,
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin,
|
||||
lockoutPolicy bool,
|
||||
actionsAllowed domain.ActionsAllowed,
|
||||
maxActions int,
|
||||
) (*instance.FeaturesSetEvent, bool) {
|
||||
|
||||
changes := make([]features.FeaturesChanges, 0)
|
||||
|
||||
if tierName != "" && wm.TierName != tierName {
|
||||
changes = append(changes, features.ChangeTierName(tierName))
|
||||
}
|
||||
if wm.TierDescription != tierDescription {
|
||||
changes = append(changes, features.ChangeTierDescription(tierDescription))
|
||||
}
|
||||
if wm.State != state {
|
||||
changes = append(changes, features.ChangeState(state))
|
||||
}
|
||||
if wm.StateDescription != stateDescription {
|
||||
changes = append(changes, features.ChangeStateDescription(stateDescription))
|
||||
}
|
||||
if auditLogRetention != 0 && wm.AuditLogRetention != auditLogRetention {
|
||||
changes = append(changes, features.ChangeAuditLogRetention(auditLogRetention))
|
||||
}
|
||||
if wm.LoginPolicyFactors != loginPolicyFactors {
|
||||
changes = append(changes, features.ChangeLoginPolicyFactors(loginPolicyFactors))
|
||||
}
|
||||
if wm.LoginPolicyIDP != loginPolicyIDP {
|
||||
changes = append(changes, features.ChangeLoginPolicyIDP(loginPolicyIDP))
|
||||
}
|
||||
if wm.LoginPolicyPasswordless != loginPolicyPasswordless {
|
||||
changes = append(changes, features.ChangeLoginPolicyPasswordless(loginPolicyPasswordless))
|
||||
}
|
||||
if wm.LoginPolicyRegistration != loginPolicyRegistration {
|
||||
changes = append(changes, features.ChangeLoginPolicyRegistration(loginPolicyRegistration))
|
||||
}
|
||||
if wm.LoginPolicyUsernameLogin != loginPolicyUsernameLogin {
|
||||
changes = append(changes, features.ChangeLoginPolicyUsernameLogin(loginPolicyUsernameLogin))
|
||||
}
|
||||
if wm.LoginPolicyPasswordReset != loginPolicyPasswordReset {
|
||||
changes = append(changes, features.ChangeLoginPolicyPasswordReset(loginPolicyPasswordReset))
|
||||
}
|
||||
if wm.PasswordComplexityPolicy != passwordComplexityPolicy {
|
||||
changes = append(changes, features.ChangePasswordComplexityPolicy(passwordComplexityPolicy))
|
||||
}
|
||||
if wm.LabelPolicyPrivateLabel != labelPolicyPrivateLabel {
|
||||
changes = append(changes, features.ChangeLabelPolicyPrivateLabel(labelPolicyPrivateLabel))
|
||||
}
|
||||
if wm.LabelPolicyWatermark != labelPolicyWatermark {
|
||||
changes = append(changes, features.ChangeLabelPolicyWatermark(labelPolicyWatermark))
|
||||
}
|
||||
if wm.CustomDomain != customDomain {
|
||||
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
||||
}
|
||||
if wm.PrivacyPolicy != privacyPolicy {
|
||||
changes = append(changes, features.ChangePrivacyPolicy(privacyPolicy))
|
||||
}
|
||||
if wm.MetadataUser != metadataUser {
|
||||
changes = append(changes, features.ChangeMetadataUser(metadataUser))
|
||||
}
|
||||
if wm.CustomTextMessage != customTextMessage {
|
||||
changes = append(changes, features.ChangeCustomTextMessage(customTextMessage))
|
||||
}
|
||||
if wm.CustomTextLogin != customTextLogin {
|
||||
changes = append(changes, features.ChangeCustomTextLogin(customTextLogin))
|
||||
}
|
||||
if wm.LockoutPolicy != lockoutPolicy {
|
||||
changes = append(changes, features.ChangeLockoutPolicy(lockoutPolicy))
|
||||
}
|
||||
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
|
||||
}
|
||||
changedEvent, err := instance.NewFeaturesSetEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,152 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/features"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
)
|
||||
|
||||
func TestSetDefaultFeatures(t *testing.T) {
|
||||
type args struct {
|
||||
a *instance.Aggregate
|
||||
tierName string
|
||||
tierDescription string
|
||||
state domain.FeaturesState
|
||||
stateDescription string
|
||||
retention time.Duration
|
||||
loginPolicyFactors bool
|
||||
loginPolicyIDP bool
|
||||
loginPolicyPasswordless bool
|
||||
loginPolicyRegistration bool
|
||||
loginPolicyUsernameLogin bool
|
||||
loginPolicyPasswordReset bool
|
||||
passwordComplexityPolicy bool
|
||||
labelPolicyPrivateLabel bool
|
||||
labelPolicyWatermark bool
|
||||
customDomain bool
|
||||
privacyPolicy bool
|
||||
metadataUser bool
|
||||
customTextMessage bool
|
||||
customTextLogin bool
|
||||
lockoutPolicy bool
|
||||
actionsAllowed domain.ActionsAllowed
|
||||
maxActions int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want Want
|
||||
}{
|
||||
{
|
||||
name: "invalid state",
|
||||
args: args{
|
||||
a: instance.NewAggregate("INSTANCE"),
|
||||
tierName: "",
|
||||
tierDescription: "",
|
||||
state: 0,
|
||||
stateDescription: "",
|
||||
retention: 0,
|
||||
loginPolicyFactors: false,
|
||||
loginPolicyIDP: false,
|
||||
loginPolicyPasswordless: false,
|
||||
loginPolicyRegistration: false,
|
||||
loginPolicyUsernameLogin: false,
|
||||
loginPolicyPasswordReset: false,
|
||||
passwordComplexityPolicy: false,
|
||||
labelPolicyPrivateLabel: false,
|
||||
labelPolicyWatermark: false,
|
||||
customDomain: false,
|
||||
privacyPolicy: false,
|
||||
metadataUser: false,
|
||||
customTextMessage: false,
|
||||
customTextLogin: false,
|
||||
lockoutPolicy: false,
|
||||
actionsAllowed: 0,
|
||||
maxActions: 0,
|
||||
},
|
||||
want: Want{
|
||||
ValidationErr: errors.ThrowInvalidArgument(nil, "INSTA-d3r1s", "Errors.Invalid.Argument"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "correct",
|
||||
args: args{
|
||||
a: instance.NewAggregate("INSTANCE"),
|
||||
tierName: "",
|
||||
tierDescription: "",
|
||||
state: domain.FeaturesStateActive,
|
||||
stateDescription: "",
|
||||
retention: 0,
|
||||
loginPolicyFactors: false,
|
||||
loginPolicyIDP: false,
|
||||
loginPolicyPasswordless: false,
|
||||
loginPolicyRegistration: false,
|
||||
loginPolicyUsernameLogin: false,
|
||||
loginPolicyPasswordReset: false,
|
||||
passwordComplexityPolicy: false,
|
||||
labelPolicyPrivateLabel: false,
|
||||
labelPolicyWatermark: false,
|
||||
customDomain: false,
|
||||
privacyPolicy: false,
|
||||
metadataUser: false,
|
||||
customTextMessage: false,
|
||||
customTextLogin: false,
|
||||
lockoutPolicy: false,
|
||||
actionsAllowed: 0,
|
||||
maxActions: 0,
|
||||
},
|
||||
want: Want{
|
||||
Commands: []eventstore.Command{
|
||||
func() *instance.FeaturesSetEvent {
|
||||
event, _ := instance.NewFeaturesSetEvent(context.Background(), &instance.NewAggregate("INSTANCE").Aggregate,
|
||||
[]features.FeaturesChanges{
|
||||
features.ChangeState(domain.FeaturesStateActive),
|
||||
},
|
||||
)
|
||||
return event
|
||||
}(),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
AssertValidation(t, SetDefaultFeatures(
|
||||
tt.args.a,
|
||||
tt.args.tierName,
|
||||
tt.args.tierDescription,
|
||||
tt.args.state,
|
||||
tt.args.stateDescription,
|
||||
tt.args.retention,
|
||||
tt.args.loginPolicyFactors,
|
||||
tt.args.loginPolicyIDP,
|
||||
tt.args.loginPolicyPasswordless,
|
||||
tt.args.loginPolicyRegistration,
|
||||
tt.args.loginPolicyUsernameLogin,
|
||||
tt.args.loginPolicyPasswordReset,
|
||||
tt.args.passwordComplexityPolicy,
|
||||
tt.args.labelPolicyPrivateLabel,
|
||||
tt.args.labelPolicyWatermark,
|
||||
tt.args.customDomain,
|
||||
tt.args.privacyPolicy,
|
||||
tt.args.metadataUser,
|
||||
tt.args.customTextMessage,
|
||||
tt.args.customTextLogin,
|
||||
tt.args.lockoutPolicy,
|
||||
tt.args.actionsAllowed,
|
||||
tt.args.maxActions,
|
||||
), NewMultiFilter().
|
||||
Append(func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
|
||||
return nil, nil
|
||||
}).
|
||||
Filter(),
|
||||
tt.want)
|
||||
})
|
||||
}
|
||||
}
|
@@ -9,9 +9,7 @@ import (
|
||||
"github.com/golang/mock/gomock"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository/mock"
|
||||
@@ -213,51 +211,6 @@ func GetMockSecretGenerator(t *testing.T) crypto.Generator {
|
||||
return generator
|
||||
}
|
||||
|
||||
func GetMockVerifier(t *testing.T, features ...string) *testVerifier {
|
||||
return &testVerifier{
|
||||
features: features,
|
||||
}
|
||||
}
|
||||
|
||||
type testVerifier struct {
|
||||
features []string
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, string, string, string, error) {
|
||||
return "userID", "agentID", "clientID", "de", "orgID", nil
|
||||
}
|
||||
func (v *testVerifier) SearchMyMemberships(ctx context.Context) ([]*authz.Membership, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
|
||||
return "", nil, nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ExistsOrg(ctx context.Context, orgID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifierClientID(ctx context.Context, appName string) (string, error) {
|
||||
return "clientID", nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) CheckOrgFeatures(ctx context.Context, orgID string, requiredFeatures ...string) error {
|
||||
for _, feature := range requiredFeatures {
|
||||
hasFeature := false
|
||||
for _, f := range v.features {
|
||||
if f == feature {
|
||||
hasFeature = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasFeature {
|
||||
return errors.ThrowPermissionDenied(nil, "id", "missing feature")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type mockInstance struct{}
|
||||
|
||||
func (m *mockInstance) InstanceID() string {
|
||||
|
@@ -15,10 +15,6 @@ 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
|
||||
@@ -44,27 +40,6 @@ 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 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")
|
||||
@@ -145,10 +120,6 @@ 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{
|
||||
|
@@ -6,8 +6,6 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/repository/features"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
@@ -56,76 +54,10 @@ 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").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").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{
|
||||
@@ -160,30 +92,6 @@ 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").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(
|
||||
@@ -663,94 +571,10 @@ 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").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").Aggregate,
|
||||
[]features.FeaturesChanges{
|
||||
features.ChangeMaxActions(1),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
action.NewAddedEvent(context.Background(),
|
||||
|
@@ -1,393 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
)
|
||||
|
||||
func (c *Commands) SetOrgFeatures(ctx context.Context, resourceOwner string, features *domain.Features) (*domain.ObjectDetails, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Features-G5tg", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
err := c.checkOrgExists(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingFeatures := NewOrgFeaturesWriteModel(resourceOwner)
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, existingFeatures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setEvent, hasChanged := existingFeatures.NewSetEvent(
|
||||
ctx,
|
||||
OrgAggregateFromWriteModel(&existingFeatures.FeaturesWriteModel.WriteModel),
|
||||
features.TierName,
|
||||
features.TierDescription,
|
||||
features.State,
|
||||
features.StateDescription,
|
||||
features.AuditLogRetention,
|
||||
features.LoginPolicyFactors,
|
||||
features.LoginPolicyIDP,
|
||||
features.LoginPolicyPasswordless,
|
||||
features.LoginPolicyRegistration,
|
||||
features.LoginPolicyUsernameLogin,
|
||||
features.LoginPolicyPasswordReset,
|
||||
features.PasswordComplexityPolicy,
|
||||
features.LabelPolicyPrivateLabel,
|
||||
features.LabelPolicyWatermark,
|
||||
features.CustomDomain,
|
||||
features.PrivacyPolicy,
|
||||
features.MetadataUser,
|
||||
features.CustomTextMessage,
|
||||
features.CustomTextLogin,
|
||||
features.LockoutPolicy,
|
||||
features.ActionsAllowed,
|
||||
features.MaxActions,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||
}
|
||||
|
||||
events, err := c.ensureOrgSettingsToFeatures(ctx, resourceOwner, features)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events = append(events, setEvent)
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingFeatures, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&existingFeatures.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveOrgFeatures(ctx context.Context, orgID string) (*domain.ObjectDetails, error) {
|
||||
if orgID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Features-G5tg", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
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 nil, caos_errs.ThrowNotFound(nil, "Features-Bg32G", "Errors.Features.NotFound")
|
||||
}
|
||||
removedEvent := org.NewFeaturesRemovedEvent(ctx, OrgAggregateFromWriteModel(&existingFeatures.FeaturesWriteModel.WriteModel))
|
||||
|
||||
features, err := c.getDefaultFeatures(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := c.ensureOrgSettingsToFeatures(ctx, orgID, features)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
events = append(events, removedEvent)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingFeatures, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&existingFeatures.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ensureOrgSettingsToFeatures(ctx context.Context, orgID string, features *domain.Features) ([]eventstore.Command, error) {
|
||||
events, err := c.setAllowedLoginPolicy(ctx, orgID, features)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !features.PasswordComplexityPolicy {
|
||||
removePasswordComplexityEvent, err := c.removePasswordComplexityPolicyIfExists(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if removePasswordComplexityEvent != nil {
|
||||
events = append(events, removePasswordComplexityEvent)
|
||||
}
|
||||
}
|
||||
labelPolicyEvents, err := c.setAllowedLabelPolicy(ctx, orgID, features)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events = append(events, labelPolicyEvents...)
|
||||
|
||||
if !features.CustomDomain {
|
||||
removeCustomDomainsEvents, err := c.removeCustomDomains(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if removeCustomDomainsEvents != nil {
|
||||
events = append(events, removeCustomDomainsEvents...)
|
||||
}
|
||||
}
|
||||
if !features.CustomTextMessage {
|
||||
removeCustomMessageTextEvents, err := c.removeOrgMessageTextsIfExists(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if removeCustomMessageTextEvents != nil {
|
||||
events = append(events, removeCustomMessageTextEvents...)
|
||||
}
|
||||
}
|
||||
if !features.CustomTextLogin {
|
||||
removeCustomLoginTextEvents, err := c.removeOrgLoginTextsIfExists(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if removeCustomLoginTextEvents != nil {
|
||||
events = append(events, removeCustomLoginTextEvents...)
|
||||
}
|
||||
}
|
||||
if !features.PrivacyPolicy {
|
||||
removePrivacyPolicyEvent, err := c.removePrivacyPolicyIfExists(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if removePrivacyPolicyEvent != nil {
|
||||
events = append(events, removePrivacyPolicyEvent)
|
||||
}
|
||||
}
|
||||
if !features.LockoutPolicy {
|
||||
removeLockoutPolicyEvent, err := c.removeLockoutPolicyIfExists(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if removeLockoutPolicyEvent != nil {
|
||||
events = append(events, removeLockoutPolicyEvent)
|
||||
}
|
||||
}
|
||||
if !features.MetadataUser {
|
||||
removeOrgUserMetadatas, err := c.removeUserMetadataFromOrg(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(removeOrgUserMetadatas) > 0 {
|
||||
events = append(events, removeOrgUserMetadatas...)
|
||||
}
|
||||
}
|
||||
if features.ActionsAllowed == domain.ActionsNotAllowed {
|
||||
removeOrgActions, err := c.removeActionsFromOrg(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(removeOrgActions) > 0 {
|
||||
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
|
||||
}
|
||||
|
||||
func (c *Commands) setAllowedLoginPolicy(ctx context.Context, orgID string, features *domain.Features) ([]eventstore.Command, error) {
|
||||
events := make([]eventstore.Command, 0)
|
||||
existingPolicy, err := c.orgLoginPolicyWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, nil
|
||||
}
|
||||
defaultPolicy, err := c.getDefaultLoginPolicy(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy := *existingPolicy
|
||||
if !features.LoginPolicyFactors {
|
||||
if defaultPolicy.ForceMFA != existingPolicy.ForceMFA {
|
||||
policy.ForceMFA = defaultPolicy.ForceMFA
|
||||
}
|
||||
authFactorsEvents, err := c.setDefaultAuthFactorsInCustomLoginPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events = append(events, authFactorsEvents...)
|
||||
}
|
||||
if !features.LoginPolicyIDP {
|
||||
if defaultPolicy.AllowExternalIDP != existingPolicy.AllowExternalIDP {
|
||||
policy.AllowExternalIDP = defaultPolicy.AllowExternalIDP
|
||||
}
|
||||
//TODO: handle idps
|
||||
}
|
||||
if !features.LoginPolicyRegistration && defaultPolicy.AllowRegister != existingPolicy.AllowRegister {
|
||||
policy.AllowRegister = defaultPolicy.AllowRegister
|
||||
}
|
||||
if !features.LoginPolicyPasswordless && defaultPolicy.PasswordlessType != existingPolicy.PasswordlessType {
|
||||
policy.PasswordlessType = defaultPolicy.PasswordlessType
|
||||
}
|
||||
if !features.LoginPolicyUsernameLogin && defaultPolicy.AllowUsernamePassword != existingPolicy.AllowUserNamePassword {
|
||||
policy.AllowUserNamePassword = defaultPolicy.AllowUsernamePassword
|
||||
}
|
||||
if !features.LoginPolicyPasswordReset && defaultPolicy.HidePasswordReset != existingPolicy.HidePasswordReset {
|
||||
policy.HidePasswordReset = defaultPolicy.HidePasswordReset
|
||||
}
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx,
|
||||
OrgAggregateFromWriteModel(&existingPolicy.WriteModel),
|
||||
policy.AllowUserNamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.PasswordlessType,
|
||||
policy.PasswordCheckLifetime,
|
||||
policy.ExternalLoginCheckLifetime,
|
||||
policy.MFAInitSkipLifetime,
|
||||
policy.SecondFactorCheckLifetime,
|
||||
policy.MultiFactorCheckLifetime)
|
||||
if hasChanged {
|
||||
events = append(events, changedEvent)
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (c *Commands) setDefaultAuthFactorsInCustomLoginPolicy(ctx context.Context, orgID string) ([]eventstore.Command, error) {
|
||||
orgAuthFactors, err := c.orgLoginPolicyAuthFactorsWriteModel(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events := make([]eventstore.Command, 0)
|
||||
for _, factor := range domain.SecondFactorTypes() {
|
||||
state := orgAuthFactors.SecondFactors[factor]
|
||||
if state == nil || state.IAM == state.Org {
|
||||
continue
|
||||
}
|
||||
secondFactorWriteModel := orgAuthFactors.ToSecondFactorWriteModel(factor)
|
||||
if state.IAM == domain.FactorStateActive {
|
||||
event, err := c.addSecondFactorToLoginPolicy(ctx, secondFactorWriteModel, factor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if event != nil {
|
||||
events = append(events, event)
|
||||
}
|
||||
continue
|
||||
}
|
||||
event, err := c.removeSecondFactorFromLoginPolicy(ctx, secondFactorWriteModel, factor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if event != nil {
|
||||
events = append(events, event)
|
||||
}
|
||||
}
|
||||
|
||||
for _, factor := range domain.MultiFactorTypes() {
|
||||
state := orgAuthFactors.MultiFactors[factor]
|
||||
if state == nil || state.IAM == state.Org {
|
||||
continue
|
||||
}
|
||||
multiFactorWriteModel := orgAuthFactors.ToMultiFactorWriteModel(factor)
|
||||
if state.IAM == domain.FactorStateActive {
|
||||
event, err := c.addMultiFactorToLoginPolicy(ctx, multiFactorWriteModel, factor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if event != nil {
|
||||
events = append(events, event)
|
||||
}
|
||||
continue
|
||||
}
|
||||
event, err := c.removeMultiFactorFromLoginPolicy(ctx, multiFactorWriteModel, factor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if event != nil {
|
||||
events = append(events, event)
|
||||
}
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (c *Commands) setAllowedLabelPolicy(ctx context.Context, orgID string, features *domain.Features) ([]eventstore.Command, error) {
|
||||
events := make([]eventstore.Command, 0)
|
||||
existingPolicy, err := c.orgLabelPolicyWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, nil
|
||||
}
|
||||
if !features.LabelPolicyPrivateLabel && !features.LabelPolicyWatermark {
|
||||
removeEvent, err := c.removeLabelPolicy(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(events, removeEvent), nil
|
||||
}
|
||||
defaultPolicy, err := c.getDefaultLabelPolicy(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy := *existingPolicy
|
||||
if !features.LabelPolicyWatermark && defaultPolicy.DisableWatermark != existingPolicy.DisableWatermark {
|
||||
policy.DisableWatermark = defaultPolicy.DisableWatermark
|
||||
}
|
||||
if !features.LabelPolicyPrivateLabel {
|
||||
if defaultPolicy.HideLoginNameSuffix != existingPolicy.HideLoginNameSuffix {
|
||||
policy.HideLoginNameSuffix = defaultPolicy.HideLoginNameSuffix
|
||||
}
|
||||
policy.PrimaryColor = ""
|
||||
policy.BackgroundColor = ""
|
||||
policy.WarnColor = ""
|
||||
policy.FontColor = ""
|
||||
policy.PrimaryColorDark = ""
|
||||
policy.BackgroundColorDark = ""
|
||||
policy.WarnColorDark = ""
|
||||
policy.FontColorDark = ""
|
||||
|
||||
assetsEvent, err := c.removeLabelPolicyAssets(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events = append(events, assetsEvent)
|
||||
}
|
||||
changedEvent, hasChangedEvent := existingPolicy.NewChangedEvent(ctx, OrgAggregateFromWriteModel(&existingPolicy.WriteModel),
|
||||
policy.PrimaryColor, policy.BackgroundColor, policy.WarnColor, policy.FontColor,
|
||||
policy.PrimaryColorDark, policy.BackgroundColorDark, policy.WarnColorDark, policy.FontColorDark,
|
||||
policy.HideLoginNameSuffix, policy.ErrorMsgPopup, policy.HideLoginNameSuffix)
|
||||
if hasChangedEvent {
|
||||
events = append(events, changedEvent)
|
||||
}
|
||||
if len(events) > 0 {
|
||||
events = append(events, org.NewLabelPolicyActivatedEvent(ctx, OrgAggregateFromWriteModel(&existingPolicy.WriteModel)))
|
||||
}
|
||||
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 := NewInstanceFeaturesWriteModel(ctx)
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, existingIAMFeatures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToFeatures(&existingIAMFeatures.FeaturesWriteModel), nil
|
||||
}
|
@@ -1,163 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/features"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
)
|
||||
|
||||
type OrgFeaturesWriteModel struct {
|
||||
FeaturesWriteModel
|
||||
}
|
||||
|
||||
func NewOrgFeaturesWriteModel(orgID string) *OrgFeaturesWriteModel {
|
||||
return &OrgFeaturesWriteModel{
|
||||
FeaturesWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgFeaturesWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.FeaturesSetEvent:
|
||||
wm.FeaturesWriteModel.AppendEvents(&e.FeaturesSetEvent)
|
||||
case *org.FeaturesRemovedEvent:
|
||||
wm.FeaturesWriteModel.AppendEvents(&e.FeaturesRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgFeaturesWriteModel) IsValid() bool {
|
||||
return wm.AggregateID != ""
|
||||
}
|
||||
|
||||
func (wm *OrgFeaturesWriteModel) Reduce() error {
|
||||
return wm.FeaturesWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgFeaturesWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(org.AggregateType).
|
||||
AggregateIDs(wm.FeaturesWriteModel.AggregateID).
|
||||
EventTypes(
|
||||
org.FeaturesSetEventType,
|
||||
org.FeaturesRemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *OrgFeaturesWriteModel) NewSetEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
tierName,
|
||||
tierDescription string,
|
||||
state domain.FeaturesState,
|
||||
stateDescription string,
|
||||
auditLogRetention time.Duration,
|
||||
loginPolicyFactors,
|
||||
loginPolicyIDP,
|
||||
loginPolicyPasswordless,
|
||||
loginPolicyRegistration,
|
||||
loginPolicyUsernameLogin,
|
||||
loginPolicyPasswordReset,
|
||||
passwordComplexityPolicy,
|
||||
labelPolicyPrivateLabel,
|
||||
labelPolicyWatermark,
|
||||
customDomain,
|
||||
privacyPolicy,
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin,
|
||||
lockoutPolicy bool,
|
||||
actionsAllowed domain.ActionsAllowed,
|
||||
maxActions int,
|
||||
) (*org.FeaturesSetEvent, bool) {
|
||||
|
||||
changes := make([]features.FeaturesChanges, 0)
|
||||
|
||||
if tierName != "" && wm.TierName != tierName {
|
||||
changes = append(changes, features.ChangeTierName(tierName))
|
||||
}
|
||||
if wm.TierDescription != tierDescription {
|
||||
changes = append(changes, features.ChangeTierDescription(tierDescription))
|
||||
}
|
||||
if wm.State != state {
|
||||
changes = append(changes, features.ChangeState(state))
|
||||
}
|
||||
if stateDescription != "" && wm.StateDescription != stateDescription {
|
||||
changes = append(changes, features.ChangeStateDescription(stateDescription))
|
||||
}
|
||||
if auditLogRetention != 0 && wm.AuditLogRetention != auditLogRetention {
|
||||
changes = append(changes, features.ChangeAuditLogRetention(auditLogRetention))
|
||||
}
|
||||
if wm.LoginPolicyFactors != loginPolicyFactors {
|
||||
changes = append(changes, features.ChangeLoginPolicyFactors(loginPolicyFactors))
|
||||
}
|
||||
if wm.LoginPolicyIDP != loginPolicyIDP {
|
||||
changes = append(changes, features.ChangeLoginPolicyIDP(loginPolicyIDP))
|
||||
}
|
||||
if wm.LoginPolicyPasswordless != loginPolicyPasswordless {
|
||||
changes = append(changes, features.ChangeLoginPolicyPasswordless(loginPolicyPasswordless))
|
||||
}
|
||||
if wm.LoginPolicyRegistration != loginPolicyRegistration {
|
||||
changes = append(changes, features.ChangeLoginPolicyRegistration(loginPolicyRegistration))
|
||||
}
|
||||
if wm.LoginPolicyUsernameLogin != loginPolicyUsernameLogin {
|
||||
changes = append(changes, features.ChangeLoginPolicyUsernameLogin(loginPolicyUsernameLogin))
|
||||
}
|
||||
if wm.LoginPolicyPasswordReset != loginPolicyPasswordReset {
|
||||
changes = append(changes, features.ChangeLoginPolicyPasswordReset(loginPolicyPasswordReset))
|
||||
}
|
||||
if wm.PasswordComplexityPolicy != passwordComplexityPolicy {
|
||||
changes = append(changes, features.ChangePasswordComplexityPolicy(passwordComplexityPolicy))
|
||||
}
|
||||
if wm.LabelPolicyPrivateLabel != labelPolicyPrivateLabel {
|
||||
changes = append(changes, features.ChangeLabelPolicyPrivateLabel(labelPolicyPrivateLabel))
|
||||
}
|
||||
if wm.LabelPolicyWatermark != labelPolicyWatermark {
|
||||
changes = append(changes, features.ChangeLabelPolicyWatermark(labelPolicyWatermark))
|
||||
}
|
||||
if wm.CustomDomain != customDomain {
|
||||
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
||||
}
|
||||
if wm.PrivacyPolicy != privacyPolicy {
|
||||
changes = append(changes, features.ChangePrivacyPolicy(privacyPolicy))
|
||||
}
|
||||
if wm.MetadataUser != metadataUser {
|
||||
changes = append(changes, features.ChangeMetadataUser(metadataUser))
|
||||
}
|
||||
if wm.CustomTextMessage != customTextMessage {
|
||||
changes = append(changes, features.ChangeCustomTextMessage(customTextMessage))
|
||||
}
|
||||
if wm.CustomTextLogin != customTextLogin {
|
||||
changes = append(changes, features.ChangeCustomTextLogin(customTextLogin))
|
||||
}
|
||||
if wm.LockoutPolicy != lockoutPolicy {
|
||||
changes = append(changes, features.ChangeLockoutPolicy(lockoutPolicy))
|
||||
}
|
||||
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
|
||||
}
|
||||
changedEvent, err := org.NewFeaturesSetEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -25,10 +25,6 @@ func (c *Commands) AddLabelPolicy(ctx context.Context, resourceOwner string, pol
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-2B0ps", "Errors.Org.LabelPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
err = c.checkLabelPolicyAllowed(ctx, resourceOwner, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, org.NewLabelPolicyAddedEvent(
|
||||
ctx,
|
||||
@@ -70,11 +66,6 @@ func (c *Commands) ChangeLabelPolicy(ctx context.Context, resourceOwner string,
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-0K9dq", "Errors.Org.LabelPolicy.NotFound")
|
||||
}
|
||||
|
||||
err = c.checkLabelPolicyAllowed(ctx, resourceOwner, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
||||
ctx,
|
||||
@@ -105,28 +96,6 @@ func (c *Commands) ChangeLabelPolicy(ctx context.Context, resourceOwner string,
|
||||
return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkLabelPolicyAllowed(ctx context.Context, resourceOwner string, policy *domain.LabelPolicy) error {
|
||||
defaultPolicy, err := c.getDefaultLabelPolicy(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requiredFeatures := make([]string, 0)
|
||||
if defaultPolicy.PrimaryColor != policy.PrimaryColor || defaultPolicy.PrimaryColorDark != policy.PrimaryColorDark ||
|
||||
defaultPolicy.FontColor != policy.FontColor || defaultPolicy.FontColorDark != policy.FontColorDark ||
|
||||
defaultPolicy.BackgroundColor != policy.BackgroundColor || defaultPolicy.BackgroundColorDark != policy.BackgroundColorDark ||
|
||||
defaultPolicy.WarnColor != defaultPolicy.WarnColor || defaultPolicy.WarnColorDark != defaultPolicy.WarnColorDark ||
|
||||
defaultPolicy.LogoURL != policy.LogoURL || defaultPolicy.LogoDarkURL != policy.LogoDarkURL ||
|
||||
defaultPolicy.IconURL != policy.IconURL || defaultPolicy.IconDarkURL != policy.IconDarkURL ||
|
||||
defaultPolicy.Font != policy.Font ||
|
||||
defaultPolicy.HideLoginNameSuffix != policy.HideLoginNameSuffix {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLabelPolicyPrivateLabel)
|
||||
}
|
||||
if defaultPolicy.DisableWatermark != policy.DisableWatermark {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLabelPolicyWatermark)
|
||||
}
|
||||
return c.tokenVerifier.CheckOrgFeatures(ctx, resourceOwner, requiredFeatures...)
|
||||
}
|
||||
|
||||
func (c *Commands) ActivateLabelPolicy(ctx context.Context, orgID string) (*domain.ObjectDetails, error) {
|
||||
if orgID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-KKd4X", "Errors.ResourceOwnerMissing")
|
||||
|
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/repository/policy"
|
||||
"github.com/zitadel/zitadel/internal/static"
|
||||
@@ -22,8 +21,7 @@ import (
|
||||
|
||||
func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
tokenVerifier orgFeatureChecker
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -104,78 +102,12 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add policy, permission denied",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLabelPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "#ffffff",
|
||||
BackgroundColor: "#ffffff",
|
||||
WarnColor: "#ffffff",
|
||||
FontColor: "#ffffff",
|
||||
PrimaryColorDark: "#ffffff",
|
||||
BackgroundColorDark: "#ffffff",
|
||||
WarnColorDark: "#ffffff",
|
||||
FontColorDark: "#ffffff",
|
||||
HideLoginNameSuffix: true,
|
||||
ErrorMsgPopup: true,
|
||||
DisableWatermark: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPermissionDenied,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add policy,ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLabelPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
@@ -197,7 +129,6 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t, domain.FeatureLabelPolicyPrivateLabel, domain.FeatureLabelPolicyWatermark),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -240,8 +171,7 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
tokenVerifier: tt.fields.tokenVerifier,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddLabelPolicy(tt.args.ctx, tt.args.orgID, tt.args.policy)
|
||||
if tt.res.err == nil {
|
||||
@@ -259,8 +189,7 @@ func TestCommandSide_AddLabelPolicy(t *testing.T) {
|
||||
|
||||
func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
tokenVerifier orgFeatureChecker
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -316,71 +245,6 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "permission denied error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewLabelPolicyAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLabelPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LabelPolicy{
|
||||
PrimaryColor: "#000000",
|
||||
BackgroundColor: "#000000",
|
||||
WarnColor: "#000000",
|
||||
FontColor: "#000000",
|
||||
PrimaryColorDark: "#000000",
|
||||
BackgroundColorDark: "#000000",
|
||||
WarnColorDark: "#000000",
|
||||
FontColorDark: "#000000",
|
||||
HideLoginNameSuffix: true,
|
||||
ErrorMsgPopup: true,
|
||||
DisableWatermark: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPermissionDenied,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
@@ -404,26 +268,7 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLabelPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t, domain.FeatureLabelPolicyPrivateLabel, domain.FeatureLabelPolicyWatermark),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -469,24 +314,6 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLabelPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
"#ffffff",
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
@@ -508,7 +335,6 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t, domain.FeatureLabelPolicyPrivateLabel, domain.FeatureLabelPolicyWatermark),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -551,8 +377,7 @@ func TestCommandSide_ChangeLabelPolicy(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
tokenVerifier: tt.fields.tokenVerifier,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeLabelPolicy(tt.args.ctx, tt.args.orgID, tt.args.policy)
|
||||
if tt.res.err == nil {
|
||||
|
@@ -2,7 +2,6 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
@@ -26,11 +25,6 @@ func (c *Commands) AddLoginPolicy(ctx context.Context, resourceOwner string, pol
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-Dgfb2", "Errors.Org.LoginPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
err = c.checkLoginPolicyAllowed(ctx, resourceOwner, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(
|
||||
ctx,
|
||||
@@ -91,11 +85,6 @@ func (c *Commands) ChangeLoginPolicy(ctx context.Context, resourceOwner string,
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-M0sif", "Errors.Org.LoginPolicy.NotFound")
|
||||
}
|
||||
|
||||
err = c.checkLoginPolicyAllowed(ctx, resourceOwner, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
||||
ctx,
|
||||
@@ -127,33 +116,6 @@ func (c *Commands) ChangeLoginPolicy(ctx context.Context, resourceOwner string,
|
||||
return writeModelToLoginPolicy(&existingPolicy.LoginPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkLoginPolicyAllowed(ctx context.Context, resourceOwner string, policy *domain.LoginPolicy) error {
|
||||
defaultPolicy, err := c.getDefaultLoginPolicy(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requiredFeatures := make([]string, 0)
|
||||
if defaultPolicy.ForceMFA != policy.ForceMFA || !reflect.DeepEqual(defaultPolicy.MultiFactors, policy.MultiFactors) || !reflect.DeepEqual(defaultPolicy.SecondFactors, policy.SecondFactors) {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLoginPolicyFactors)
|
||||
}
|
||||
if defaultPolicy.AllowExternalIDP != policy.AllowExternalIDP || !reflect.DeepEqual(defaultPolicy.IDPProviders, policy.IDPProviders) {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLoginPolicyIDP)
|
||||
}
|
||||
if defaultPolicy.AllowRegister != policy.AllowRegister {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLoginPolicyRegistration)
|
||||
}
|
||||
if defaultPolicy.PasswordlessType != policy.PasswordlessType {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLoginPolicyPasswordless)
|
||||
}
|
||||
if defaultPolicy.AllowUsernamePassword != policy.AllowUsernamePassword {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLoginPolicyUsernameLogin)
|
||||
}
|
||||
if defaultPolicy.HidePasswordReset != policy.HidePasswordReset {
|
||||
requiredFeatures = append(requiredFeatures, domain.FeatureLoginPolicyPasswordReset)
|
||||
}
|
||||
return c.tokenVerifier.CheckOrgFeatures(ctx, resourceOwner, requiredFeatures...)
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveLoginPolicy(ctx context.Context, orgID string) (*domain.ObjectDetails, error) {
|
||||
if orgID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-55Mg9", "Errors.ResourceOwnerMissing")
|
||||
|
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/repository/policy"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
@@ -28,8 +27,7 @@ var (
|
||||
|
||||
func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
tokenVerifier orgFeatureChecker
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -110,77 +108,12 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "loginpolicy not allowed, permission denied error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
MFAInitSkipLifetime: time.Hour * 3,
|
||||
SecondFactorCheckLifetime: time.Hour * 4,
|
||||
MultiFactorCheckLifetime: time.Hour * 5,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPermissionDenied,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add policy,ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
@@ -202,7 +135,6 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t, domain.FeatureLoginPolicyUsernameLogin),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -245,8 +177,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
tokenVerifier: tt.fields.tokenVerifier,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddLoginPolicy(tt.args.ctx, tt.args.orgID, tt.args.policy)
|
||||
if tt.res.err == nil {
|
||||
@@ -264,8 +195,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
|
||||
func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
tokenVerifier orgFeatureChecker
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -326,70 +256,6 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not allowed, permission denied error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
MFAInitSkipLifetime: time.Hour * 3,
|
||||
SecondFactorCheckLifetime: time.Hour * 4,
|
||||
MultiFactorCheckLifetime: time.Hour * 5,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPermissionDenied,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
@@ -413,26 +279,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t, domain.FeatureLoginPolicyUsernameLogin),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -478,24 +325,6 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
@@ -517,7 +346,6 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
tokenVerifier: GetMockVerifier(t, domain.FeatureLoginPolicyUsernameLogin),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -559,8 +387,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
tokenVerifier: tt.fields.tokenVerifier,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeLoginPolicy(tt.args.ctx, tt.args.orgID, tt.args.policy)
|
||||
if tt.res.err == nil {
|
||||
|
Reference in New Issue
Block a user