mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 18:17:35 +00:00
fix: move v2 pkgs (#1331)
* fix: move eventstore pkgs * fix: move eventstore pkgs * fix: remove v2 view * fix: remove v2 view
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
func checkExplicitProjectPermission(ctx context.Context, grantID, projectID string) error {
|
||||
permissions := authz.GetRequestPermissionsFromCtx(ctx)
|
||||
if authz.HasGlobalPermission(permissions) {
|
||||
return nil
|
||||
}
|
||||
ids := authz.GetAllPermissionCtxIDs(permissions)
|
||||
if grantID != "" && listContainsID(ids, grantID) {
|
||||
return nil
|
||||
}
|
||||
if listContainsID(ids, projectID) {
|
||||
return nil
|
||||
}
|
||||
return caos_errors.ThrowPermissionDenied(nil, "EVENT-Shu7e", "Errors.UserGrant.NoPermissionForProject")
|
||||
}
|
||||
|
||||
func listContainsID(ids []string, id string) bool {
|
||||
for _, i := range ids {
|
||||
if i == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@@ -1,143 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/http"
|
||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/id"
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
keypair "github.com/caos/zitadel/internal/v2/repository/keypair"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
proj_repo "github.com/caos/zitadel/internal/v2/repository/project"
|
||||
usr_repo "github.com/caos/zitadel/internal/v2/repository/user"
|
||||
usr_grant_repo "github.com/caos/zitadel/internal/v2/repository/usergrant"
|
||||
webauthn_helper "github.com/caos/zitadel/internal/webauthn"
|
||||
)
|
||||
|
||||
type CommandSide struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
iamDomain string
|
||||
|
||||
idpConfigSecretCrypto crypto.Crypto
|
||||
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
initializeUserCode crypto.Generator
|
||||
emailVerificationCode crypto.Generator
|
||||
phoneVerificationCode crypto.Generator
|
||||
passwordVerificationCode crypto.Generator
|
||||
machineKeyAlg crypto.EncryptionAlgorithm
|
||||
machineKeySize int
|
||||
applicationKeySize int
|
||||
applicationSecretGenerator crypto.Generator
|
||||
domainVerificationAlg *crypto.AESCrypto
|
||||
domainVerificationGenerator crypto.Generator
|
||||
domainVerificationValidator func(domain, token, verifier string, checkType http.CheckType) error
|
||||
//TODO: remove global model, or move to domain
|
||||
multifactors global_model.Multifactors
|
||||
|
||||
webauthn *webauthn_helper.WebAuthN
|
||||
keySize int
|
||||
keyAlgorithm crypto.EncryptionAlgorithm
|
||||
privateKeyLifetime time.Duration
|
||||
publicKeyLifetime time.Duration
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Eventstore *eventstore.Eventstore
|
||||
SystemDefaults sd.SystemDefaults
|
||||
}
|
||||
|
||||
func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
||||
repo = &CommandSide{
|
||||
eventstore: config.Eventstore,
|
||||
idGenerator: id.SonyFlakeGenerator,
|
||||
iamDomain: config.SystemDefaults.Domain,
|
||||
keySize: config.SystemDefaults.KeyConfig.Size,
|
||||
privateKeyLifetime: config.SystemDefaults.KeyConfig.PrivateKeyLifetime.Duration,
|
||||
publicKeyLifetime: config.SystemDefaults.KeyConfig.PublicKeyLifetime.Duration,
|
||||
}
|
||||
iam_repo.RegisterEventMappers(repo.eventstore)
|
||||
org.RegisterEventMappers(repo.eventstore)
|
||||
usr_repo.RegisterEventMappers(repo.eventstore)
|
||||
usr_grant_repo.RegisterEventMappers(repo.eventstore)
|
||||
proj_repo.RegisterEventMappers(repo.eventstore)
|
||||
keypair.RegisterEventMappers(repo.eventstore)
|
||||
|
||||
//TODO: simplify!!!!
|
||||
repo.idpConfigSecretCrypto, err = crypto.NewAESCrypto(config.SystemDefaults.IDPConfigVerificationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userEncryptionAlgorithm, err := crypto.NewAESCrypto(config.SystemDefaults.UserVerificationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.initializeUserCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.InitializeUserCode, userEncryptionAlgorithm)
|
||||
repo.emailVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.EmailVerificationCode, userEncryptionAlgorithm)
|
||||
repo.phoneVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.PhoneVerificationCode, userEncryptionAlgorithm)
|
||||
repo.passwordVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.PasswordVerificationCode, userEncryptionAlgorithm)
|
||||
repo.userPasswordAlg = crypto.NewBCrypt(config.SystemDefaults.SecretGenerators.PasswordSaltCost)
|
||||
repo.machineKeyAlg = userEncryptionAlgorithm
|
||||
repo.machineKeySize = int(config.SystemDefaults.SecretGenerators.MachineKeySize)
|
||||
repo.applicationKeySize = int(config.SystemDefaults.SecretGenerators.ApplicationKeySize)
|
||||
|
||||
aesOTPCrypto, err := crypto.NewAESCrypto(config.SystemDefaults.Multifactors.OTP.VerificationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.multifactors = global_model.Multifactors{
|
||||
OTP: global_model.OTP{
|
||||
CryptoMFA: aesOTPCrypto,
|
||||
Issuer: config.SystemDefaults.Multifactors.OTP.Issuer,
|
||||
},
|
||||
}
|
||||
passwordAlg := crypto.NewBCrypt(config.SystemDefaults.SecretGenerators.PasswordSaltCost)
|
||||
repo.applicationSecretGenerator = crypto.NewHashGenerator(config.SystemDefaults.SecretGenerators.ClientSecretGenerator, passwordAlg)
|
||||
|
||||
repo.domainVerificationAlg, err = crypto.NewAESCrypto(config.SystemDefaults.DomainVerification.VerificationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.domainVerificationGenerator = crypto.NewEncryptionGenerator(config.SystemDefaults.DomainVerification.VerificationGenerator, repo.domainVerificationAlg)
|
||||
repo.domainVerificationValidator = http.ValidateDomain
|
||||
web, err := webauthn_helper.StartServer(config.SystemDefaults.WebAuthN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.webauthn = web
|
||||
|
||||
keyAlgorithm, err := crypto.NewAESCrypto(config.SystemDefaults.KeyConfig.EncryptionConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.keyAlgorithm = keyAlgorithm
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getIAMWriteModel(ctx context.Context) (_ *IAMWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMWriteModel()
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
||||
|
||||
func AppendAndReduce(object interface {
|
||||
AppendEvents(...eventstore.EventReader)
|
||||
Reduce() error
|
||||
}, events ...eventstore.EventReader) error {
|
||||
object.AppendEvents(events...)
|
||||
return object.Reduce()
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
//TODO: private
|
||||
func (r *CommandSide) GetIAM(ctx context.Context) (*domain.IAM, error) {
|
||||
iamWriteModel := NewIAMWriteModel()
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, iamWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIAM(iamWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) setGlobalOrg(ctx context.Context, iamAgg *eventstore.Aggregate, iamWriteModel *IAMWriteModel, orgID string) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, iamWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if iamWriteModel.GlobalOrgID != "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-HGG24", "Errors.IAM.GlobalOrgAlreadySet")
|
||||
}
|
||||
return iam.NewGlobalOrgSetEventEvent(ctx, iamAgg, orgID), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) setIAMProject(ctx context.Context, iamAgg *eventstore.Aggregate, iamWriteModel *IAMWriteModel, projectID string) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, iamWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if iamWriteModel.ProjectID != "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-EGbw2", "Errors.IAM.IAMProjectAlreadySet")
|
||||
}
|
||||
return iam.NewIAMProjectSetEvent(ctx, iamAgg, projectID), nil
|
||||
}
|
@@ -1,161 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
func writeModelToObjectRoot(writeModel eventstore.WriteModel) models.ObjectRoot {
|
||||
return models.ObjectRoot{
|
||||
AggregateID: writeModel.AggregateID,
|
||||
ChangeDate: writeModel.ChangeDate,
|
||||
ResourceOwner: writeModel.ResourceOwner,
|
||||
Sequence: writeModel.ProcessedSequence,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToIAM(wm *IAMWriteModel) *domain.IAM {
|
||||
return &domain.IAM{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
SetUpStarted: wm.SetUpStarted,
|
||||
SetUpDone: wm.SetUpDone,
|
||||
GlobalOrgID: wm.GlobalOrgID,
|
||||
IAMProjectID: wm.ProjectID,
|
||||
}
|
||||
}
|
||||
|
||||
func memberWriteModelToMember(writeModel *MemberWriteModel) *domain.Member {
|
||||
return &domain.Member{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
Roles: writeModel.Roles,
|
||||
UserID: writeModel.UserID,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToLoginPolicy(wm *LoginPolicyWriteModel) *domain.LoginPolicy {
|
||||
return &domain.LoginPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
AllowUsernamePassword: wm.AllowUserNamePassword,
|
||||
AllowRegister: wm.AllowRegister,
|
||||
AllowExternalIDP: wm.AllowExternalIDP,
|
||||
ForceMFA: wm.ForceMFA,
|
||||
PasswordlessType: wm.PasswordlessType,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToLabelPolicy(wm *LabelPolicyWriteModel) *domain.LabelPolicy {
|
||||
return &domain.LabelPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
PrimaryColor: wm.PrimaryColor,
|
||||
SecondaryColor: wm.SecondaryColor,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToMailTemplate(wm *MailTemplateWriteModel) *domain.MailTemplate {
|
||||
return &domain.MailTemplate{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
Template: wm.Template,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToMailText(wm *MailTextWriteModel) *domain.MailText {
|
||||
return &domain.MailText{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
MailTextType: wm.MailTextType,
|
||||
Language: wm.Language,
|
||||
Title: wm.Title,
|
||||
PreHeader: wm.PreHeader,
|
||||
Subject: wm.Subject,
|
||||
Greeting: wm.Greeting,
|
||||
Text: wm.Text,
|
||||
ButtonText: wm.ButtonText,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToOrgIAMPolicy(wm *IAMOrgIAMPolicyWriteModel) *domain.OrgIAMPolicy {
|
||||
return &domain.OrgIAMPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
||||
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToMailTemplatePolicy(wm *MailTemplateWriteModel) *domain.MailTemplate {
|
||||
return &domain.MailTemplate{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
Template: wm.Template,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToMailTextPolicy(wm *MailTextWriteModel) *domain.MailText {
|
||||
return &domain.MailText{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
State: wm.State,
|
||||
MailTextType: wm.MailTextType,
|
||||
Language: wm.Language,
|
||||
Title: wm.Title,
|
||||
PreHeader: wm.PreHeader,
|
||||
Subject: wm.Subject,
|
||||
Greeting: wm.Greeting,
|
||||
Text: wm.Text,
|
||||
ButtonText: wm.ButtonText,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToPasswordAgePolicy(wm *PasswordAgePolicyWriteModel) *domain.PasswordAgePolicy {
|
||||
return &domain.PasswordAgePolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
MaxAgeDays: wm.MaxAgeDays,
|
||||
ExpireWarnDays: wm.ExpireWarnDays,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToPasswordComplexityPolicy(wm *PasswordComplexityPolicyWriteModel) *domain.PasswordComplexityPolicy {
|
||||
return &domain.PasswordComplexityPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
MinLength: wm.MinLength,
|
||||
HasLowercase: wm.HasLowercase,
|
||||
HasUppercase: wm.HasUppercase,
|
||||
HasNumber: wm.HasNumber,
|
||||
HasSymbol: wm.HasSymbol,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToPasswordLockoutPolicy(wm *PasswordLockoutPolicyWriteModel) *domain.PasswordLockoutPolicy {
|
||||
return &domain.PasswordLockoutPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
MaxAttempts: wm.MaxAttempts,
|
||||
ShowLockOutFailures: wm.ShowLockOutFailures,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToIDPConfig(wm *IDPConfigWriteModel) *domain.IDPConfig {
|
||||
return &domain.IDPConfig{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
OIDCConfig: writeModelToIDPOIDCConfig(wm.OIDCConfig),
|
||||
IDPConfigID: wm.ConfigID,
|
||||
Name: wm.Name,
|
||||
State: wm.State,
|
||||
StylingType: wm.StylingType,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToIDPOIDCConfig(wm *OIDCConfigWriteModel) *domain.OIDCIDPConfig {
|
||||
return &domain.OIDCIDPConfig{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
ClientID: wm.ClientID,
|
||||
IDPConfigID: wm.IDPConfigID,
|
||||
IDPDisplayNameMapping: wm.IDPDisplayNameMapping,
|
||||
Issuer: wm.Issuer,
|
||||
Scopes: wm.Scopes,
|
||||
UsernameMapping: wm.UserNameMapping,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToIDPProvider(wm *IdentityProviderWriteModel) *domain.IDPProvider {
|
||||
return &domain.IDPProvider{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
IDPConfigID: wm.IDPConfigID,
|
||||
Type: wm.IDPProviderType,
|
||||
}
|
||||
}
|
@@ -1,154 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddDefaultIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
|
||||
if config.OIDCConfig == nil {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "IAM-eUpQU", "Errors.idp.config.notset")
|
||||
}
|
||||
|
||||
idpConfigID, err := r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedConfig := NewIAMIDPConfigWriteModel(idpConfigID)
|
||||
|
||||
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.idpConfigSecretCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedConfig.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
iam_repo.NewIDPConfigAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
idpConfigID,
|
||||
config.Name,
|
||||
config.Type,
|
||||
config.StylingType,
|
||||
),
|
||||
iam_repo.NewIDPOIDCConfigAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
config.OIDCConfig.ClientID,
|
||||
idpConfigID,
|
||||
config.OIDCConfig.Issuer,
|
||||
clientSecret,
|
||||
config.OIDCConfig.IDPDisplayNameMapping,
|
||||
config.OIDCConfig.UsernameMapping,
|
||||
config.OIDCConfig.Scopes...,
|
||||
),
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedConfig, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPConfig(&addedConfig.IDPConfigWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
|
||||
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, config.IDPConfigID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotExisting")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, iamAgg, config.IDPConfigID, config.Name, config.StylingType)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingIDP, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPConfig(&existingIDP.IDPConfigWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) DeactivateDefaultIDPConfig(ctx context.Context, idpID string) error {
|
||||
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, idpID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingIDP.State != domain.IDPConfigStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotActive")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, iam_repo.NewIDPConfigDeactivatedEvent(ctx, iamAgg, idpID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, idpID string) error {
|
||||
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, idpID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingIDP.State != domain.IDPConfigStateInactive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mo0d", "Errors.IAM.IDPConfig.NotInactive")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, iam_repo.NewIDPConfigReactivatedEvent(ctx, iamAgg, idpID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string, idpProviders []*domain.IDPProvider, externalIDPs ...*domain.ExternalIDP) error {
|
||||
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, idpID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
||||
return caos_errs.ThrowNotFound(nil, "IAM-4M0xy", "Errors.IAM.IDPConfig.NotExisting")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
iam_repo.NewIDPConfigRemovedEvent(ctx, iamAgg, idpID, existingIDP.Name),
|
||||
}
|
||||
|
||||
for _, idpProvider := range idpProviders {
|
||||
if idpProvider.AggregateID == domain.IAMID {
|
||||
userEvents := r.removeIDPProviderFromDefaultLoginPolicy(ctx, iamAgg, idpProvider, true, externalIDPs...)
|
||||
events = append(events, userEvents...)
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpID).WriteModel)
|
||||
orgEvents := r.removeIDPProviderFromLoginPolicy(ctx, orgAgg, idpID, true)
|
||||
events = append(events, orgEvents...)
|
||||
}
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) iamIDPConfigWriteModelByID(ctx context.Context, idpID string) (policy *IAMIDPConfigWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMIDPConfigWriteModel(idpID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,119 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
|
||||
)
|
||||
|
||||
type IAMIDPConfigWriteModel struct {
|
||||
IDPConfigWriteModel
|
||||
}
|
||||
|
||||
func NewIAMIDPConfigWriteModel(configID string) *IAMIDPConfigWriteModel {
|
||||
return &IAMIDPConfigWriteModel{
|
||||
IDPConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
ConfigID: configID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIDPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.IDPConfigAddedEventType,
|
||||
iam.IDPConfigChangedEventType,
|
||||
iam.IDPConfigDeactivatedEventType,
|
||||
iam.IDPConfigReactivatedEventType,
|
||||
iam.IDPConfigRemovedEventType,
|
||||
iam.IDPOIDCConfigAddedEventType,
|
||||
iam.IDPOIDCConfigChangedEventType,
|
||||
)
|
||||
}
|
||||
|
||||
func (wm *IAMIDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.IDPConfigAddedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigAddedEvent)
|
||||
case *iam.IDPConfigChangedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigChangedEvent)
|
||||
case *iam.IDPConfigDeactivatedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
|
||||
case *iam.IDPConfigReactivatedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
|
||||
case *iam.IDPConfigRemovedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
|
||||
case *iam.IDPOIDCConfigAddedEvent:
|
||||
if wm.ConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
|
||||
case *iam.IDPOIDCConfigChangedEvent:
|
||||
if wm.ConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIDPConfigWriteModel) Reduce() error {
|
||||
return wm.IDPConfigWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventReader) error {
|
||||
wm.AppendEvents(events...)
|
||||
return wm.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
configID,
|
||||
name string,
|
||||
stylingType domain.IDPConfigStylingType,
|
||||
) (*iam.IDPConfigChangedEvent, bool) {
|
||||
|
||||
changes := make([]idpconfig.IDPConfigChanges, 0)
|
||||
oldName := ""
|
||||
if wm.Name != name {
|
||||
oldName = wm.Name
|
||||
changes = append(changes, idpconfig.ChangeName(name))
|
||||
}
|
||||
if stylingType.Valid() && wm.StylingType != stylingType {
|
||||
changes = append(changes, idpconfig.ChangeStyleType(stylingType))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changeEvent, err := iam.NewIDPConfigChangedEvent(ctx, aggregate, configID, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changeEvent, true
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
func (r *CommandSide) ChangeDefaultIDPOIDCConfig(ctx context.Context, config *domain.OIDCIDPConfig) (*domain.OIDCIDPConfig, error) {
|
||||
existingConfig := NewIAMIDPOIDCConfigWriteModel(config.IDPConfigID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existingConfig.State == domain.IDPConfigStateRemoved || existingConfig.State == domain.IDPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-67J9d", "Errors.IAM.IDPConfig.AlreadyExists")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingConfig.WriteModel)
|
||||
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
config.IDPConfigID,
|
||||
config.ClientID,
|
||||
config.Issuer,
|
||||
config.ClientSecretString,
|
||||
r.idpConfigSecretCrypto,
|
||||
config.IDPDisplayNameMapping,
|
||||
config.UsernameMapping,
|
||||
config.Scopes...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingConfig, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPOIDCConfig(&existingConfig.OIDCConfigWriteModel), nil
|
||||
}
|
@@ -1,129 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
|
||||
)
|
||||
|
||||
type IAMIDPOIDCConfigWriteModel struct {
|
||||
OIDCConfigWriteModel
|
||||
}
|
||||
|
||||
func NewIAMIDPOIDCConfigWriteModel(idpConfigID string) *IAMIDPOIDCConfigWriteModel {
|
||||
return &IAMIDPOIDCConfigWriteModel{
|
||||
OIDCConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
IDPConfigID: idpConfigID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.IDPOIDCConfigAddedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
|
||||
case *iam.IDPOIDCConfigChangedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
|
||||
case *iam.IDPConfigReactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
|
||||
case *iam.IDPConfigDeactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
|
||||
case *iam.IDPConfigRemovedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
|
||||
default:
|
||||
wm.OIDCConfigWriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIDPOIDCConfigWriteModel) Reduce() error {
|
||||
if err := wm.OIDCConfigWriteModel.Reduce(); err != nil {
|
||||
return err
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMIDPOIDCConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.IDPOIDCConfigAddedEventType,
|
||||
iam.IDPOIDCConfigChangedEventType,
|
||||
iam.IDPConfigReactivatedEventType,
|
||||
iam.IDPConfigDeactivatedEventType,
|
||||
iam.IDPConfigRemovedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMIDPOIDCConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
idpConfigID,
|
||||
clientID,
|
||||
issuer,
|
||||
clientSecretString string,
|
||||
secretCrypto crypto.Crypto,
|
||||
idpDisplayNameMapping,
|
||||
userNameMapping domain.OIDCMappingField,
|
||||
scopes ...string,
|
||||
) (*iam.IDPOIDCConfigChangedEvent, bool, error) {
|
||||
|
||||
changes := make([]idpconfig.OIDCConfigChanges, 0)
|
||||
var clientSecret *crypto.CryptoValue
|
||||
var err error
|
||||
if clientSecretString != "" {
|
||||
clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
changes = append(changes, idpconfig.ChangeClientSecret(clientSecret))
|
||||
}
|
||||
if wm.ClientID != clientID {
|
||||
changes = append(changes, idpconfig.ChangeClientID(clientID))
|
||||
}
|
||||
if wm.Issuer != issuer {
|
||||
changes = append(changes, idpconfig.ChangeIssuer(issuer))
|
||||
}
|
||||
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
|
||||
changes = append(changes, idpconfig.ChangeIDPDisplayNameMapping(idpDisplayNameMapping))
|
||||
}
|
||||
if userNameMapping.Valid() && wm.UserNameMapping != userNameMapping {
|
||||
changes = append(changes, idpconfig.ChangeUserNameMapping(userNameMapping))
|
||||
}
|
||||
if !reflect.DeepEqual(wm.Scopes, scopes) {
|
||||
changes = append(changes, idpconfig.ChangeScopes(scopes))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := iam.NewIDPOIDCConfigChangedEvent(ctx, aggregate, idpConfigID, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
@@ -1,110 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
addedMember := NewIAMMemberWriteModel(member.UserID)
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedMember.MemberWriteModel.WriteModel)
|
||||
event, err := r.addIAMMember(ctx, iamAgg, addedMember, member)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addIAMMember(ctx context.Context, iamAgg *eventstore.Aggregate, addedMember *IAMMemberWriteModel, member *domain.Member) (eventstore.EventPusher, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-GR34U", "Errors.IAM.MemberInvalid")
|
||||
}
|
||||
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedMember)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedMember.State == domain.MemberStateActive {
|
||||
return nil, errors.ThrowAlreadyExists(nil, "IAM-sdgQ4", "Errors.IAM.Member.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewMemberAddedEvent(ctx, iamAgg, member.UserID, member.Roles...), nil
|
||||
}
|
||||
|
||||
//ChangeIAMMember updates an existing member
|
||||
func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-LiaZi", "Errors.IAM.MemberInvalid")
|
||||
}
|
||||
|
||||
existingMember, err := r.iamMemberWriteModelByID(ctx, member.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(existingMember.Roles, member.Roles) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-LiaZi", "Errors.IAM.Member.RolesNotChanged")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingMember.MemberWriteModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, iam_repo.NewMemberChangedEvent(ctx, iamAgg, member.UserID, member.Roles...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveIAMMember(ctx context.Context, userID string) error {
|
||||
m, err := r.iamMemberWriteModelByID(ctx, userID)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, iam_repo.NewMemberRemovedEvent(ctx, iamAgg, userID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) iamMemberWriteModelByID(ctx context.Context, userID string) (member *IAMMemberWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMMemberWriteModel(userID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if writeModel.State == domain.MemberStateUnspecified || writeModel.State == domain.MemberStateRemoved {
|
||||
return nil, errors.ThrowNotFound(nil, "IAM-D8JxR", "Errors.NotFound")
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
type IAMMemberWriteModel struct {
|
||||
MemberWriteModel
|
||||
}
|
||||
|
||||
func NewIAMMemberWriteModel(userID string) *IAMMemberWriteModel {
|
||||
return &IAMMemberWriteModel{
|
||||
MemberWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
UserID: userID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.MemberAddedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberAddedEvent)
|
||||
case *iam.MemberChangedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberChangedEvent)
|
||||
case *iam.MemberRemovedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMemberWriteModel) Reduce() error {
|
||||
return wm.MemberWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.MemberWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.MemberAddedEventType,
|
||||
iam.MemberChangedEventType,
|
||||
iam.MemberRemovedEventType)
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
type IAMWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
SetUpStarted domain.Step
|
||||
SetUpDone domain.Step
|
||||
|
||||
GlobalOrgID string
|
||||
ProjectID string
|
||||
}
|
||||
|
||||
func NewIAMWriteModel() *IAMWriteModel {
|
||||
return &IAMWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *iam.ProjectSetEvent:
|
||||
wm.ProjectID = e.ProjectID
|
||||
case *iam.GlobalOrgSetEvent:
|
||||
wm.GlobalOrgID = e.OrgID
|
||||
case *iam.SetupStepEvent:
|
||||
if e.Done {
|
||||
wm.SetUpDone = e.Step
|
||||
} else {
|
||||
wm.SetUpStarted = e.Step
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wm *IAMWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.ProjectSetEventType,
|
||||
iam.GlobalOrgSetEventType,
|
||||
iam.SetupStartedEventType,
|
||||
iam.SetupDoneEventType)
|
||||
}
|
||||
|
||||
func IAMAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
|
||||
return eventstore.AggregateFromWriteModel(wm, iam.AggregateType, iam.AggregateVersion)
|
||||
}
|
@@ -1,80 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddDefaultLabelPolicy(ctx context.Context, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) {
|
||||
addedPolicy := NewIAMLabelPolicyWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
event, err := r.addDefaultLabelPolicy(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLabelPolicy(&addedPolicy.LabelPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultLabelPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMLabelPolicyWriteModel, policy *domain.LabelPolicy) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewLabelPolicyAddedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor), nil
|
||||
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultLabelPolicy(ctx context.Context, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) {
|
||||
existingPolicy, err := r.defaultLabelPolicyWriteModelByID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.PrimaryColor, policy.SecondaryColor)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultLabelPolicyWriteModelByID(ctx context.Context) (policy *IAMLabelPolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMLabelPolicyWriteModel()
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMLabelPolicyWriteModel struct {
|
||||
LabelPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewIAMLabelPolicyWriteModel() *IAMLabelPolicyWriteModel {
|
||||
return &IAMLabelPolicyWriteModel{
|
||||
LabelPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMLabelPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.LabelPolicyAddedEvent:
|
||||
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyAddedEvent)
|
||||
case *iam.LabelPolicyChangedEvent:
|
||||
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMLabelPolicyWriteModel) Reduce() error {
|
||||
return wm.LabelPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMLabelPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.LabelPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.LabelPolicyAddedEventType,
|
||||
iam.LabelPolicyChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMLabelPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
primaryColor,
|
||||
secondaryColor string,
|
||||
) (*iam.LabelPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.LabelPolicyChanges, 0)
|
||||
if wm.PrimaryColor != primaryColor {
|
||||
changes = append(changes, policy.ChangePrimaryColor(primaryColor))
|
||||
}
|
||||
if wm.SecondaryColor != secondaryColor {
|
||||
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewLabelPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,238 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) getDefaultLoginPolicy(ctx context.Context) (*domain.LoginPolicy, error) {
|
||||
policyWriteModel := NewIAMLoginPolicyWriteModel()
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy := writeModelToLoginPolicy(&policyWriteModel.LoginPolicyWriteModel)
|
||||
policy.Default = true
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddDefaultLoginPolicy(ctx context.Context, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
addedPolicy := NewIAMLoginPolicyWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
event, err := r.addDefaultLoginPolicy(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToLoginPolicy(&addedPolicy.LoginPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultLoginPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMLoginPolicyWriteModel, policy *domain.LoginPolicy) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewLoginPolicyAddedEvent(ctx, iamAgg, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIDP, policy.ForceMFA, policy.PasswordlessType), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultLoginPolicy(ctx context.Context, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
existingPolicy := NewIAMLoginPolicyWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
event, err := r.changeDefaultLoginPolicy(ctx, iamAgg, existingPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLoginPolicy(&existingPolicy.LoginPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) changeDefaultLoginPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, existingPolicy *IAMLoginPolicyWriteModel, policy *domain.LoginPolicy) (eventstore.EventPusher, error) {
|
||||
err := r.defaultLoginPolicyWriteModelByID(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-M0sif", "Errors.IAM.LoginPolicy.NotFound")
|
||||
}
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIDP, policy.ForceMFA, policy.PasswordlessType)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
|
||||
}
|
||||
return changedEvent, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) (*domain.IDPProvider, error) {
|
||||
idpModel := NewIAMIdentityProviderWriteModel(idpProvider.IDPConfigID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if idpModel.State == domain.IdentityProviderStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.IDP.AlreadyExists")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&idpModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, iam_repo.NewIdentityProviderAddedEvent(ctx, iamAgg, idpProvider.IDPConfigID, idpProvider.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(idpModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.ExternalIDP) error {
|
||||
idpModel := NewIAMIdentityProviderWriteModel(idpProvider.IDPConfigID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if idpModel.State == domain.IdentityProviderStateUnspecified || idpModel.State == domain.IdentityProviderStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "IAM-39fjs", "Errors.IAM.LoginPolicy.IDP.NotExisting")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
iam_repo.NewIdentityProviderRemovedEvent(ctx, iamAgg, idpProvider.IDPConfigID),
|
||||
}
|
||||
|
||||
userEvents := r.removeIDPProviderFromDefaultLoginPolicy(ctx, iamAgg, idpProvider, false, cascadeExternalIDPs...)
|
||||
events = append(events, userEvents...)
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) removeIDPProviderFromDefaultLoginPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, idpProvider *domain.IDPProvider, cascade bool, cascadeExternalIDPs ...*domain.ExternalIDP) []eventstore.EventPusher {
|
||||
var events []eventstore.EventPusher
|
||||
if cascade {
|
||||
events = append(events, iam_repo.NewIdentityProviderCascadeRemovedEvent(ctx, iamAgg, idpProvider.IDPConfigID))
|
||||
} else {
|
||||
events = append(events, iam_repo.NewIdentityProviderRemovedEvent(ctx, iamAgg, idpProvider.IDPConfigID))
|
||||
}
|
||||
|
||||
for _, idp := range cascadeExternalIDPs {
|
||||
userEvent, err := r.removeHumanExternalIDP(ctx, idp, true)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-4nfsf", "userid", idp.AggregateID, "idp-id", idp.IDPConfigID).WithError(err).Warn("could not cascade remove externalidp in remove provider from policy")
|
||||
continue
|
||||
}
|
||||
events = append(events, userEvent)
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType) (domain.SecondFactorType, error) {
|
||||
secondFactorModel := NewIAMSecondFactorWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
|
||||
event, err := r.addSecondFactorToDefaultLoginPolicy(ctx, iamAgg, secondFactorModel, secondFactor)
|
||||
if err != nil {
|
||||
return domain.SecondFactorTypeUnspecified, err
|
||||
}
|
||||
|
||||
if _, err = r.eventstore.PushEvents(ctx, event); err != nil {
|
||||
return domain.SecondFactorTypeUnspecified, err
|
||||
}
|
||||
|
||||
return secondFactorModel.MFAType, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addSecondFactorToDefaultLoginPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, secondFactorModel *IAMSecondFactorWriteModel, secondFactor domain.SecondFactorType) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if secondFactorModel.State == domain.FactorStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
|
||||
}
|
||||
return iam_repo.NewLoginPolicySecondFactorAddedEvent(ctx, iamAgg, secondFactor), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType) error {
|
||||
secondFactorModel := NewIAMSecondFactorWriteModel()
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if secondFactorModel.State == domain.FactorStateUnspecified || secondFactorModel.State == domain.FactorStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.NotExisting")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, iam_repo.NewLoginPolicySecondFactorRemovedEvent(ctx, iamAgg, secondFactor))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddMultiFactorToDefaultLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType) (domain.MultiFactorType, error) {
|
||||
multiFactorModel := NewIAMMultiFactorWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
|
||||
event, err := r.addMultiFactorToDefaultLoginPolicy(ctx, iamAgg, multiFactorModel, multiFactor)
|
||||
if err != nil {
|
||||
return domain.MultiFactorTypeUnspecified, err
|
||||
}
|
||||
|
||||
if _, err = r.eventstore.PushEvents(ctx, event); err != nil {
|
||||
return domain.MultiFactorTypeUnspecified, err
|
||||
}
|
||||
|
||||
return multiFactorModel.MultiFactoryWriteModel.MFAType, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addMultiFactorToDefaultLoginPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, multiFactorModel *IAMMultiFactorWriteModel, multiFactor domain.MultiFactorType) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if multiFactorModel.State == domain.FactorStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewLoginPolicyMultiFactorAddedEvent(ctx, iamAgg, multiFactor), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveMultiFactorFromDefaultLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType) error {
|
||||
multiFactorModel := NewIAMMultiFactorWriteModel()
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if multiFactorModel.State == domain.FactorStateUnspecified || multiFactorModel.State == domain.FactorStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "IAM-3M9df", "Errors.IAM.LoginPolicy.MFA.NotExisting")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, iam_repo.NewLoginPolicyMultiFactorRemovedEvent(ctx, iamAgg, multiFactor))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultLoginPolicyWriteModelByID(ctx context.Context, writeModel *IAMLoginPolicyWriteModel) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -1,85 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
type IAMSecondFactorWriteModel struct {
|
||||
SecondFactorWriteModel
|
||||
}
|
||||
|
||||
func NewIAMSecondFactorWriteModel() *IAMSecondFactorWriteModel {
|
||||
return &IAMSecondFactorWriteModel{
|
||||
SecondFactorWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSecondFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.LoginPolicySecondFactorAddedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.SecondFactorAddedEvent)
|
||||
case *iam.LoginPolicySecondFactorRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.SecondFactorRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSecondFactorWriteModel) Reduce() error {
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMSecondFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.WriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.LoginPolicySecondFactorAddedEventType,
|
||||
iam.LoginPolicySecondFactorRemovedEventType)
|
||||
}
|
||||
|
||||
type IAMMultiFactorWriteModel struct {
|
||||
MultiFactoryWriteModel
|
||||
}
|
||||
|
||||
func NewIAMMultiFactorWriteModel() *IAMMultiFactorWriteModel {
|
||||
return &IAMMultiFactorWriteModel{
|
||||
MultiFactoryWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMultiFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.LoginPolicyMultiFactorAddedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.MultiFactorAddedEvent)
|
||||
case *iam.LoginPolicyMultiFactorRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.MultiFactorRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMultiFactorWriteModel) Reduce() error {
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMMultiFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.WriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.LoginPolicyMultiFactorAddedEventType,
|
||||
iam.LoginPolicyMultiFactorRemovedEventType)
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
type IAMIdentityProviderWriteModel struct {
|
||||
IdentityProviderWriteModel
|
||||
}
|
||||
|
||||
func NewIAMIdentityProviderWriteModel(idpConfigID string) *IAMIdentityProviderWriteModel {
|
||||
return &IAMIdentityProviderWriteModel{
|
||||
IdentityProviderWriteModel: IdentityProviderWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
IDPConfigID: idpConfigID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIdentityProviderWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.IdentityProviderAddedEvent:
|
||||
if e.IDPConfigID != wm.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderAddedEvent)
|
||||
case *iam.IdentityProviderRemovedEvent:
|
||||
if e.IDPConfigID != wm.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIdentityProviderWriteModel) Reduce() error {
|
||||
return wm.IdentityProviderWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMIdentityProviderWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner)
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMLoginPolicyWriteModel struct {
|
||||
LoginPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewIAMLoginPolicyWriteModel() *IAMLoginPolicyWriteModel {
|
||||
return &IAMLoginPolicyWriteModel{
|
||||
LoginPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMLoginPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.LoginPolicyAddedEvent:
|
||||
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyAddedEvent)
|
||||
case *iam.LoginPolicyChangedEvent:
|
||||
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMLoginPolicyWriteModel) IsValid() bool {
|
||||
return wm.AggregateID != ""
|
||||
}
|
||||
|
||||
func (wm *IAMLoginPolicyWriteModel) Reduce() error {
|
||||
return wm.LoginPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMLoginPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.LoginPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.LoginPolicyAddedEventType,
|
||||
iam.LoginPolicyChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMLoginPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
allowUsernamePassword,
|
||||
allowRegister,
|
||||
allowExternalIDP,
|
||||
forceMFA bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
) (*iam.LoginPolicyChangedEvent, bool) {
|
||||
|
||||
changes := make([]policy.LoginPolicyChanges, 0)
|
||||
if wm.AllowUserNamePassword != allowUsernamePassword {
|
||||
changes = append(changes, policy.ChangeAllowUserNamePassword(allowUsernamePassword))
|
||||
}
|
||||
if wm.AllowRegister != allowRegister {
|
||||
changes = append(changes, policy.ChangeAllowRegister(allowRegister))
|
||||
}
|
||||
if wm.AllowExternalIDP != allowExternalIDP {
|
||||
changes = append(changes, policy.ChangeAllowExternalIDP(allowExternalIDP))
|
||||
}
|
||||
if wm.ForceMFA != forceMFA {
|
||||
changes = append(changes, policy.ChangeForceMFA(forceMFA))
|
||||
}
|
||||
if passwordlessType.Valid() && wm.PasswordlessType != passwordlessType {
|
||||
changes = append(changes, policy.ChangePasswordlessType(passwordlessType))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewLoginPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,86 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddDefaultMailTemplate(ctx context.Context, policy *domain.MailTemplate) (*domain.MailTemplate, error) {
|
||||
addedPolicy := NewIAMMailTemplateWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.MailTemplateWriteModel.WriteModel)
|
||||
event, err := r.addDefaultMailTemplate(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToMailTemplatePolicy(&addedPolicy.MailTemplateWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultMailTemplate(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMMailTemplateWriteModel, policy *domain.MailTemplate) (eventstore.EventPusher, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-fm9sd", "Errors.IAM.MailTemplate.Invalid")
|
||||
}
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-5n8fs", "Errors.IAM.MailTemplate.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewMailTemplateAddedEvent(ctx, iamAgg, policy.Template), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultMailTemplate(ctx context.Context, policy *domain.MailTemplate) (*domain.MailTemplate, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4m9ds", "Errors.IAM.MailTemplate.Invalid")
|
||||
}
|
||||
existingPolicy, err := r.defaultMailTemplateWriteModelByID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-2N8fs", "Errors.IAM.MailTemplate.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.MailTemplateWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.Template)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-3nfsG", "Errors.IAM.MailTemplate.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToMailTemplatePolicy(&existingPolicy.MailTemplateWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultMailTemplateWriteModelByID(ctx context.Context) (policy *IAMMailTemplateWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMMailTemplateWriteModel()
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMMailTemplateWriteModel struct {
|
||||
MailTemplateWriteModel
|
||||
}
|
||||
|
||||
func NewIAMMailTemplateWriteModel() *IAMMailTemplateWriteModel {
|
||||
return &IAMMailTemplateWriteModel{
|
||||
MailTemplateWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMailTemplateWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.MailTemplateAddedEvent:
|
||||
wm.MailTemplateWriteModel.AppendEvents(&e.MailTemplateAddedEvent)
|
||||
case *iam.MailTemplateChangedEvent:
|
||||
wm.MailTemplateWriteModel.AppendEvents(&e.MailTemplateChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMailTemplateWriteModel) Reduce() error {
|
||||
return wm.MailTemplateWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMMailTemplateWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.MailTemplateWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.MailTemplateAddedEventType,
|
||||
iam.MailTemplateChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMMailTemplateWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
template []byte,
|
||||
) (*iam.MailTemplateChangedEvent, bool) {
|
||||
changes := make([]policy.MailTemplateChanges, 0)
|
||||
if !reflect.DeepEqual(wm.Template, template) {
|
||||
changes = append(changes, policy.ChangeTemplate(template))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewMailTemplateChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,106 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddDefaultMailText(ctx context.Context, policy *domain.MailText) (*domain.MailText, error) {
|
||||
addedPolicy := NewIAMMailTextWriteModel(policy.MailTextType, policy.Language)
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.MailTextWriteModel.WriteModel)
|
||||
event, err := r.addDefaultMailText(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToMailTextPolicy(&addedPolicy.MailTextWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultMailText(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMMailTextWriteModel, mailText *domain.MailText) (eventstore.EventPusher, error) {
|
||||
if !mailText.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-3n8fs", "Errors.IAM.MailText.Invalid")
|
||||
}
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-9o0pM", "Errors.IAM.MailText.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewMailTextAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
mailText.MailTextType,
|
||||
mailText.Language,
|
||||
mailText.Title,
|
||||
mailText.PreHeader,
|
||||
mailText.Subject,
|
||||
mailText.Greeting,
|
||||
mailText.Text,
|
||||
mailText.ButtonText), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultMailText(ctx context.Context, mailText *domain.MailText) (*domain.MailText, error) {
|
||||
if !mailText.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-kd9fs", "Errors.IAM.MailText.Invalid")
|
||||
}
|
||||
existingPolicy, err := r.defaultMailTextWriteModelByID(ctx, mailText.MailTextType, mailText.Language)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-2N8fs", "Errors.IAM.MailText.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.MailTextWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
mailText.MailTextType,
|
||||
mailText.Language,
|
||||
mailText.Title,
|
||||
mailText.PreHeader,
|
||||
mailText.Subject,
|
||||
mailText.Greeting,
|
||||
mailText.Text,
|
||||
mailText.ButtonText)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-m9L0s", "Errors.IAM.MailText.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToMailTextPolicy(&existingPolicy.MailTextWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultMailTextWriteModelByID(ctx context.Context, mailTextType, language string) (policy *IAMMailTextWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMMailTextWriteModel(mailTextType, language)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,91 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMMailTextWriteModel struct {
|
||||
MailTextWriteModel
|
||||
}
|
||||
|
||||
func NewIAMMailTextWriteModel(mailTextType, language string) *IAMMailTextWriteModel {
|
||||
return &IAMMailTextWriteModel{
|
||||
MailTextWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
MailTextType: mailTextType,
|
||||
Language: language,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMailTextWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.MailTextAddedEvent:
|
||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextAddedEvent)
|
||||
case *iam.MailTextChangedEvent:
|
||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMMailTextWriteModel) Reduce() error {
|
||||
return wm.MailTextWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMMailTextWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.MailTextWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.MailTextAddedEventType,
|
||||
iam.MailTextChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMMailTextWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
mailTextType,
|
||||
language,
|
||||
title,
|
||||
preHeader,
|
||||
subject,
|
||||
greeting,
|
||||
text,
|
||||
buttonText string,
|
||||
) (*iam.MailTextChangedEvent, bool) {
|
||||
changes := make([]policy.MailTextChanges, 0)
|
||||
if wm.Title != title {
|
||||
changes = append(changes, policy.ChangeTitle(title))
|
||||
}
|
||||
if wm.PreHeader != preHeader {
|
||||
changes = append(changes, policy.ChangePreHeader(preHeader))
|
||||
}
|
||||
if wm.Subject != subject {
|
||||
changes = append(changes, policy.ChangeSubject(subject))
|
||||
}
|
||||
if wm.Greeting != greeting {
|
||||
changes = append(changes, policy.ChangeGreeting(greeting))
|
||||
}
|
||||
if wm.Text != text {
|
||||
changes = append(changes, policy.ChangeText(text))
|
||||
}
|
||||
if wm.ButtonText != buttonText {
|
||||
changes = append(changes, policy.ChangeButtonText(buttonText))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewMailTextChangedEvent(ctx, aggregate, mailTextType, language, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,88 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddDefaultOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||
addedPolicy := NewIAMOrgIAMPolicyWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
event, err := r.addDefaultOrgIAMPolicy(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToOrgIAMPolicy(addedPolicy), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultOrgIAMPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMOrgIAMPolicyWriteModel, policy *domain.OrgIAMPolicy) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.OrgIAMPolicy.AlreadyExists")
|
||||
}
|
||||
return iam_repo.NewOrgIAMPolicyAddedEvent(ctx, iamAgg, policy.UserLoginMustBeDomain), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||
existingPolicy, err := r.defaultOrgIAMPolicyWriteModelByID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-0Pl0d", "Errors.IAM.OrgIAMPolicy.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.UserLoginMustBeDomain)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToOrgIAMPolicy(existingPolicy), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getDefaultOrgIAMPolicy(ctx context.Context) (*domain.OrgIAMPolicy, error) {
|
||||
policyWriteModel, err := r.defaultOrgIAMPolicyWriteModelByID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy := writeModelToOrgIAMPolicy(policyWriteModel)
|
||||
policy.Default = true
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultOrgIAMPolicyWriteModelByID(ctx context.Context) (policy *IAMOrgIAMPolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMOrgIAMPolicyWriteModel()
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMOrgIAMPolicyWriteModel struct {
|
||||
PolicyOrgIAMWriteModel
|
||||
}
|
||||
|
||||
func NewIAMOrgIAMPolicyWriteModel() *IAMOrgIAMPolicyWriteModel {
|
||||
return &IAMOrgIAMPolicyWriteModel{
|
||||
PolicyOrgIAMWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMOrgIAMPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.OrgIAMPolicyAddedEvent:
|
||||
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyAddedEvent)
|
||||
case *iam.OrgIAMPolicyChangedEvent:
|
||||
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMOrgIAMPolicyWriteModel) Reduce() error {
|
||||
return wm.PolicyOrgIAMWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.PolicyOrgIAMWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.OrgIAMPolicyAddedEventType,
|
||||
iam.OrgIAMPolicyChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMOrgIAMPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
userLoginMustBeDomain bool) (*iam.OrgIAMPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.OrgIAMPolicyChanges, 0)
|
||||
if wm.UserLoginMustBeDomain != userLoginMustBeDomain {
|
||||
changes = append(changes, policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewOrgIAMPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,81 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddDefaultPasswordAgePolicy(ctx context.Context, policy *domain.PasswordAgePolicy) (*domain.PasswordAgePolicy, error) {
|
||||
addedPolicy := NewIAMPasswordAgePolicyWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
event, err := r.addDefaultPasswordAgePolicy(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordAgePolicy(&addedPolicy.PasswordAgePolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultPasswordAgePolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMPasswordAgePolicyWriteModel, policy *domain.PasswordAgePolicy) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordAgePolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewPasswordAgePolicyAddedEvent(ctx, iamAgg, policy.ExpireWarnDays, policy.MaxAgeDays), nil
|
||||
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *domain.PasswordAgePolicy) (*domain.PasswordAgePolicy, error) {
|
||||
existingPolicy, err := r.defaultPasswordAgePolicyWriteModelByID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordAgePolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.ExpireWarnDays, policy.MaxAgeDays)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToPasswordAgePolicy(&existingPolicy.PasswordAgePolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultPasswordAgePolicyWriteModelByID(ctx context.Context) (policy *IAMPasswordAgePolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMPasswordAgePolicyWriteModel()
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,71 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMPasswordAgePolicyWriteModel struct {
|
||||
PasswordAgePolicyWriteModel
|
||||
}
|
||||
|
||||
func NewIAMPasswordAgePolicyWriteModel() *IAMPasswordAgePolicyWriteModel {
|
||||
return &IAMPasswordAgePolicyWriteModel{
|
||||
PasswordAgePolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordAgePolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.PasswordAgePolicyAddedEvent:
|
||||
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyAddedEvent)
|
||||
case *iam.PasswordAgePolicyChangedEvent:
|
||||
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordAgePolicyWriteModel) Reduce() error {
|
||||
return wm.PasswordAgePolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordAgePolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.PasswordAgePolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.PasswordAgePolicyAddedEventType,
|
||||
iam.PasswordAgePolicyChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordAgePolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
expireWarnDays,
|
||||
maxAgeDays uint64) (*iam.PasswordAgePolicyChangedEvent, bool) {
|
||||
changes := make([]policy.PasswordAgePolicyChanges, 0)
|
||||
if wm.ExpireWarnDays != expireWarnDays {
|
||||
changes = append(changes, policy.ChangeExpireWarnDays(expireWarnDays))
|
||||
}
|
||||
if wm.MaxAgeDays != maxAgeDays {
|
||||
changes = append(changes, policy.ChangeMaxAgeDays(maxAgeDays))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewPasswordAgePolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,97 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) getDefaultPasswordComplexityPolicy(ctx context.Context) (*domain.PasswordComplexityPolicy, error) {
|
||||
policyWriteModel := NewIAMPasswordComplexityPolicyWriteModel()
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy := writeModelToPasswordComplexityPolicy(&policyWriteModel.PasswordComplexityPolicyWriteModel)
|
||||
policy.Default = true
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *domain.PasswordComplexityPolicy) (*domain.PasswordComplexityPolicy, error) {
|
||||
addedPolicy := NewIAMPasswordComplexityPolicyWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
events, err := r.addDefaultPasswordComplexityPolicy(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordComplexityPolicy(&addedPolicy.PasswordComplexityPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultPasswordComplexityPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMPasswordComplexityPolicyWriteModel, policy *domain.PasswordComplexityPolicy) (eventstore.EventPusher, error) {
|
||||
if err := policy.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordComplexityPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewPasswordComplexityPolicyAddedEvent(ctx, iamAgg, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *domain.PasswordComplexityPolicy) (*domain.PasswordComplexityPolicy, error) {
|
||||
if err := policy.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingPolicy, err := r.defaultPasswordComplexityPolicyWriteModelByID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordComplexityPolicy(&existingPolicy.PasswordComplexityPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultPasswordComplexityPolicyWriteModelByID(ctx context.Context) (policy *IAMPasswordComplexityPolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMPasswordComplexityPolicyWriteModel()
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,85 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMPasswordComplexityPolicyWriteModel struct {
|
||||
PasswordComplexityPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewIAMPasswordComplexityPolicyWriteModel() *IAMPasswordComplexityPolicyWriteModel {
|
||||
return &IAMPasswordComplexityPolicyWriteModel{
|
||||
PasswordComplexityPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordComplexityPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.PasswordComplexityPolicyAddedEvent:
|
||||
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent)
|
||||
case *iam.PasswordComplexityPolicyChangedEvent:
|
||||
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordComplexityPolicyWriteModel) Reduce() error {
|
||||
return wm.PasswordComplexityPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordComplexityPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.PasswordComplexityPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.PasswordComplexityPolicyAddedEventType,
|
||||
iam.PasswordComplexityPolicyChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordComplexityPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
minLength uint64,
|
||||
hasLowercase,
|
||||
hasUppercase,
|
||||
hasNumber,
|
||||
hasSymbol bool,
|
||||
) (*iam.PasswordComplexityPolicyChangedEvent, bool) {
|
||||
|
||||
changes := make([]policy.PasswordComplexityPolicyChanges, 0)
|
||||
if wm.MinLength != minLength {
|
||||
changes = append(changes, policy.ChangeMinLength(minLength))
|
||||
}
|
||||
if wm.HasLowercase != hasLowercase {
|
||||
changes = append(changes, policy.ChangeHasLowercase(hasLowercase))
|
||||
}
|
||||
if wm.HasUppercase != hasUppercase {
|
||||
changes = append(changes, policy.ChangeHasUppercase(hasUppercase))
|
||||
}
|
||||
if wm.HasNumber != hasNumber {
|
||||
changes = append(changes, policy.ChangeHasNumber(hasNumber))
|
||||
}
|
||||
if wm.HasSymbol != hasSymbol {
|
||||
changes = append(changes, policy.ChangeHasSymbol(hasSymbol))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewPasswordComplexityPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *domain.PasswordLockoutPolicy) (*domain.PasswordLockoutPolicy, error) {
|
||||
addedPolicy := NewIAMPasswordLockoutPolicyWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
event, err := r.addDefaultPasswordLockoutPolicy(ctx, iamAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToPasswordLockoutPolicy(&addedPolicy.PasswordLockoutPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addDefaultPasswordLockoutPolicy(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMPasswordLockoutPolicyWriteModel, policy *domain.PasswordLockoutPolicy) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0olDf", "Errors.IAM.PasswordLockoutPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
return iam_repo.NewPasswordLockoutPolicyAddedEvent(ctx, iamAgg, policy.MaxAttempts, policy.ShowLockOutFailures), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *domain.PasswordLockoutPolicy) (*domain.PasswordLockoutPolicy, error) {
|
||||
existingPolicy, err := r.defaultPasswordLockoutPolicyWriteModelByID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-0oPew", "Errors.IAM.PasswordLockoutPolicy.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.MaxAttempts, policy.ShowLockOutFailures)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.PasswordLockoutPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordLockoutPolicy(&existingPolicy.PasswordLockoutPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultPasswordLockoutPolicyWriteModelByID(ctx context.Context) (policy *IAMPasswordLockoutPolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMPasswordLockoutPolicyWriteModel()
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,71 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IAMPasswordLockoutPolicyWriteModel struct {
|
||||
PasswordLockoutPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewIAMPasswordLockoutPolicyWriteModel() *IAMPasswordLockoutPolicyWriteModel {
|
||||
return &IAMPasswordLockoutPolicyWriteModel{
|
||||
PasswordLockoutPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordLockoutPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.PasswordLockoutPolicyAddedEvent:
|
||||
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyAddedEvent)
|
||||
case *iam.PasswordLockoutPolicyChangedEvent:
|
||||
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordLockoutPolicyWriteModel) Reduce() error {
|
||||
return wm.PasswordLockoutPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordLockoutPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.PasswordLockoutPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
iam.PasswordLockoutPolicyAddedEventType,
|
||||
iam.PasswordLockoutPolicyChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *IAMPasswordLockoutPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
maxAttempts uint64,
|
||||
showLockoutFailure bool) (*iam.PasswordLockoutPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.PasswordLockoutPolicyChanges, 0)
|
||||
if wm.MaxAttempts != maxAttempts {
|
||||
changes = append(changes, policy.ChangeMaxAttempts(maxAttempts))
|
||||
}
|
||||
if wm.ShowLockOutFailures != showLockoutFailure {
|
||||
changes = append(changes, policy.ChangeShowLockOutFailures(showLockoutFailure))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewPasswordLockoutPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type IdentityProviderWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
IDPConfigID string
|
||||
IDPProviderType domain.IdentityProviderType
|
||||
State domain.IdentityProviderState
|
||||
}
|
||||
|
||||
func (wm *IdentityProviderWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.IdentityProviderAddedEvent:
|
||||
wm.IDPConfigID = e.IDPConfigID
|
||||
wm.IDPProviderType = e.IDPProviderType
|
||||
wm.State = domain.IdentityProviderStateActive
|
||||
case *policy.IdentityProviderRemovedEvent:
|
||||
wm.State = domain.IdentityProviderStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
|
||||
)
|
||||
|
||||
type IDPConfigWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
State domain.IDPConfigState
|
||||
|
||||
ConfigID string
|
||||
Name string
|
||||
StylingType domain.IDPConfigStylingType
|
||||
|
||||
//TODO: sub writemodels not used anymore?
|
||||
OIDCConfig *OIDCConfigWriteModel
|
||||
}
|
||||
|
||||
func (rm *IDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
rm.WriteModel.AppendEvents(events...)
|
||||
for _, event := range events {
|
||||
switch event.(type) {
|
||||
case *idpconfig.OIDCConfigAddedEvent:
|
||||
rm.OIDCConfig = new(OIDCConfigWriteModel)
|
||||
rm.OIDCConfig.AppendEvents(event)
|
||||
case *idpconfig.OIDCConfigChangedEvent:
|
||||
rm.OIDCConfig.AppendEvents(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rm *IDPConfigWriteModel) Reduce() error {
|
||||
for _, event := range rm.Events {
|
||||
switch e := event.(type) {
|
||||
case *idpconfig.IDPConfigAddedEvent:
|
||||
rm.reduceConfigAddedEvent(e)
|
||||
case *idpconfig.IDPConfigChangedEvent:
|
||||
rm.reduceConfigChangedEvent(e)
|
||||
case *idpconfig.IDPConfigDeactivatedEvent:
|
||||
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateInactive)
|
||||
case *idpconfig.IDPConfigReactivatedEvent:
|
||||
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateActive)
|
||||
case *idpconfig.IDPConfigRemovedEvent:
|
||||
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateRemoved)
|
||||
}
|
||||
}
|
||||
if rm.OIDCConfig != nil {
|
||||
if err := rm.OIDCConfig.Reduce(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return rm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (rm *IDPConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.IDPConfigAddedEvent) {
|
||||
rm.ConfigID = e.ConfigID
|
||||
rm.Name = e.Name
|
||||
rm.StylingType = e.StylingType
|
||||
rm.State = domain.IDPConfigStateActive
|
||||
}
|
||||
|
||||
func (rm *IDPConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.IDPConfigChangedEvent) {
|
||||
if e.Name != nil {
|
||||
rm.Name = *e.Name
|
||||
}
|
||||
if e.StylingType != nil && e.StylingType.Valid() {
|
||||
rm.StylingType = *e.StylingType
|
||||
}
|
||||
}
|
||||
|
||||
func (rm *IDPConfigWriteModel) reduceConfigStateChanged(configID string, state domain.IDPConfigState) {
|
||||
rm.State = state
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
keypair "github.com/caos/zitadel/internal/v2/repository/keypair"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
oidcUser = "OIDC"
|
||||
)
|
||||
|
||||
func (r *CommandSide) GenerateSigningKeyPair(ctx context.Context, algorithm string) error {
|
||||
ctx = setOIDCCtx(ctx)
|
||||
privateCrypto, publicCrypto, err := crypto.GenerateEncryptedKeyPair(r.keySize, r.keyAlgorithm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyID, err := r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privateKeyExp := time.Now().UTC().Add(r.privateKeyLifetime)
|
||||
publicKeyExp := time.Now().UTC().Add(r.publicKeyLifetime)
|
||||
|
||||
keyPairWriteModel := NewKeyPairWriteModel(keyID, domain.IAMID)
|
||||
keyAgg := KeyPairAggregateFromWriteModel(&keyPairWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, keypair.NewAddedEvent(
|
||||
ctx,
|
||||
keyAgg,
|
||||
domain.KeyUsageSigning,
|
||||
algorithm,
|
||||
privateCrypto, publicCrypto,
|
||||
privateKeyExp, publicKeyExp))
|
||||
return err
|
||||
}
|
||||
|
||||
func setOIDCCtx(ctx context.Context) context.Context {
|
||||
return authz.SetCtxData(ctx, authz.CtxData{UserID: oidcUser, OrgID: domain.IAMID})
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
keypair "github.com/caos/zitadel/internal/v2/repository/keypair"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type KeyPairWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Usage domain.KeyUsage
|
||||
Algorithm string
|
||||
PrivateKey *domain.Key
|
||||
PublicKey *domain.Key
|
||||
}
|
||||
|
||||
func NewKeyPairWriteModel(aggregateID, resourceOwner string) *KeyPairWriteModel {
|
||||
return &KeyPairWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: aggregateID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *KeyPairWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
wm.WriteModel.AppendEvents(events...)
|
||||
}
|
||||
|
||||
func (wm *KeyPairWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *keypair.AddedEvent:
|
||||
wm.Usage = e.Usage
|
||||
wm.Algorithm = e.Algorithm
|
||||
wm.PrivateKey = &domain.Key{
|
||||
Key: e.PrivateKey.Key,
|
||||
Expiry: e.PrivateKey.Expiry,
|
||||
}
|
||||
wm.PublicKey = &domain.Key{
|
||||
Key: e.PublicKey.Key,
|
||||
Expiry: e.PublicKey.Expiry,
|
||||
}
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *KeyPairWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(keypair.AddedEventType)
|
||||
}
|
||||
|
||||
func KeyPairAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
|
||||
return eventstore.AggregateFromWriteModel(wm, keypair.AggregateType, keypair.AggregateVersion)
|
||||
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/member"
|
||||
)
|
||||
|
||||
type MemberWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
UserID string
|
||||
Roles []string
|
||||
|
||||
State domain.MemberState
|
||||
}
|
||||
|
||||
func NewMemberWriteModel(userID string) *MemberWriteModel {
|
||||
return &MemberWriteModel{
|
||||
UserID: userID,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *MemberWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *member.MemberAddedEvent:
|
||||
wm.UserID = e.UserID
|
||||
wm.Roles = e.Roles
|
||||
wm.State = domain.MemberStateActive
|
||||
case *member.MemberChangedEvent:
|
||||
wm.Roles = e.Roles
|
||||
case *member.MemberRemovedEvent:
|
||||
wm.Roles = nil
|
||||
wm.State = domain.MemberStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
|
||||
)
|
||||
|
||||
type OIDCConfigWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
IDPConfigID string
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
Issuer string
|
||||
Scopes []string
|
||||
|
||||
IDPDisplayNameMapping domain.OIDCMappingField
|
||||
UserNameMapping domain.OIDCMappingField
|
||||
State domain.IDPConfigState
|
||||
}
|
||||
|
||||
func (wm *OIDCConfigWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *idpconfig.OIDCConfigAddedEvent:
|
||||
wm.reduceConfigAddedEvent(e)
|
||||
case *idpconfig.OIDCConfigChangedEvent:
|
||||
wm.reduceConfigChangedEvent(e)
|
||||
case *idpconfig.IDPConfigDeactivatedEvent:
|
||||
wm.State = domain.IDPConfigStateInactive
|
||||
case *idpconfig.IDPConfigReactivatedEvent:
|
||||
wm.State = domain.IDPConfigStateActive
|
||||
case *idpconfig.IDPConfigRemovedEvent:
|
||||
wm.State = domain.IDPConfigStateRemoved
|
||||
}
|
||||
}
|
||||
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OIDCConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAddedEvent) {
|
||||
wm.IDPConfigID = e.IDPConfigID
|
||||
wm.ClientID = e.ClientID
|
||||
wm.ClientSecret = e.ClientSecret
|
||||
wm.Issuer = e.Issuer
|
||||
wm.Scopes = e.Scopes
|
||||
wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping
|
||||
wm.UserNameMapping = e.UserNameMapping
|
||||
wm.State = domain.IDPConfigStateActive
|
||||
}
|
||||
|
||||
func (wm *OIDCConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfigChangedEvent) {
|
||||
if e.ClientID != nil {
|
||||
wm.ClientID = *e.ClientID
|
||||
}
|
||||
if e.Issuer != nil {
|
||||
wm.Issuer = *e.Issuer
|
||||
}
|
||||
if len(e.Scopes) > 0 {
|
||||
wm.Scopes = e.Scopes
|
||||
}
|
||||
if e.IDPDisplayNameMapping != nil && e.IDPDisplayNameMapping.Valid() {
|
||||
wm.IDPDisplayNameMapping = *e.IDPDisplayNameMapping
|
||||
}
|
||||
if e.UserNameMapping != nil && e.UserNameMapping.Valid() {
|
||||
wm.UserNameMapping = *e.UserNameMapping
|
||||
}
|
||||
}
|
@@ -1,158 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) getOrg(ctx context.Context, orgID string) (*domain.Org, error) {
|
||||
writeModel, err := r.getOrgWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if writeModel.State == domain.OrgStateUnspecified || writeModel.State == domain.OrgStateRemoved {
|
||||
return nil, caos_errs.ThrowInternal(err, "COMMAND-4M9sf", "Errors.Org.NotFound")
|
||||
}
|
||||
return orgWriteModelToOrg(writeModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) checkOrgExists(ctx context.Context, orgID string) error {
|
||||
orgWriteModel, err := r.getOrgWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if orgWriteModel.State == domain.OrgStateUnspecified || orgWriteModel.State == domain.OrgStateRemoved {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0fs", "Errors.Org.NotFound")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human) error {
|
||||
_, _, _, events, err := r.setUpOrg(ctx, organisation, admin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddOrg(ctx context.Context, name, userID, resourceOwner string) (*domain.Org, error) {
|
||||
orgAgg, addedOrg, events, err := r.addOrg(ctx, &domain.Org{Name: name})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = r.checkUserExists(ctx, userID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedMember := NewOrgMemberWriteModel(addedOrg.AggregateID, userID)
|
||||
orgMemberEvent, err := r.addOrgMember(ctx, orgAgg, addedMember, domain.NewMember(orgAgg.ID, userID, domain.RoleOrgOwner))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events = append(events, orgMemberEvent)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedOrg, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orgWriteModelToOrg(addedOrg), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) DeactivateOrg(ctx context.Context, orgID string) error {
|
||||
orgWriteModel, err := r.getOrgWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if orgWriteModel.State == domain.OrgStateUnspecified || orgWriteModel.State == domain.OrgStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "ORG-oL9nT", "Errors.Org.NotFound")
|
||||
}
|
||||
if orgWriteModel.State == domain.OrgStateInactive {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "EVENT-Dbs2g", "Errors.Org.AlreadyDeactivated")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewOrgDeactivatedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) ReactivateOrg(ctx context.Context, orgID string) error {
|
||||
orgWriteModel, err := r.getOrgWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if orgWriteModel.State == domain.OrgStateUnspecified || orgWriteModel.State == domain.OrgStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "ORG-Dgf3g", "Errors.Org.NotFound")
|
||||
}
|
||||
if orgWriteModel.State == domain.OrgStateActive {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "EVENT-bfnrh", "Errors.Org.AlreadyActive")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewOrgReactivatedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) setUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human) (orgAgg *eventstore.Aggregate, human *HumanWriteModel, orgMember *OrgMemberWriteModel, events []eventstore.EventPusher, err error) {
|
||||
orgAgg, _, addOrgEvents, err := r.addOrg(ctx, organisation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
userEvents, human, err := r.addHuman(ctx, orgAgg.ID, admin)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
addOrgEvents = append(addOrgEvents, userEvents...)
|
||||
|
||||
addedMember := NewOrgMemberWriteModel(orgAgg.ID, human.AggregateID)
|
||||
orgMemberAgg := OrgAggregateFromWriteModel(&addedMember.WriteModel)
|
||||
orgMemberEvent, err := r.addOrgMember(ctx, orgMemberAgg, addedMember, domain.NewMember(orgMemberAgg.ID, human.AggregateID, domain.RoleOrgOwner))
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
addOrgEvents = append(addOrgEvents, orgMemberEvent)
|
||||
return orgAgg, human, addedMember, addOrgEvents, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrg(ctx context.Context, organisation *domain.Org, claimedUserIDs ...string) (_ *eventstore.Aggregate, _ *OrgWriteModel, _ []eventstore.EventPusher, err error) {
|
||||
if organisation == nil || !organisation.IsValid() {
|
||||
return nil, nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMM-deLSk", "Errors.Org.Invalid")
|
||||
}
|
||||
|
||||
organisation.AggregateID, err = r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, nil, nil, caos_errs.ThrowInternal(err, "COMMA-OwciI", "Errors.Internal")
|
||||
}
|
||||
organisation.AddIAMDomain(r.iamDomain)
|
||||
addedOrg := NewOrgWriteModel(organisation.AggregateID)
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedOrg.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
org.NewOrgAddedEvent(ctx, orgAgg, organisation.Name),
|
||||
}
|
||||
for _, orgDomain := range organisation.Domains {
|
||||
orgDomainEvents, err := r.addOrgDomain(ctx, orgAgg, NewOrgDomainWriteModel(orgAgg.ID, orgDomain.Domain), orgDomain, claimedUserIDs...)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
} else {
|
||||
events = append(events, orgDomainEvents...)
|
||||
}
|
||||
}
|
||||
return orgAgg, addedOrg, events, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getOrgWriteModelByID(ctx context.Context, orgID string) (*OrgWriteModel, error) {
|
||||
orgWriteModel := NewOrgWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, orgWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orgWriteModel, nil
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
func orgWriteModelToOrg(wm *OrgWriteModel) *domain.Org {
|
||||
return &domain.Org{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
Name: wm.Name,
|
||||
State: wm.State,
|
||||
PrimaryDomain: wm.PrimaryDomain,
|
||||
}
|
||||
}
|
||||
|
||||
func orgWriteModelToOrgIAMPolicy(wm *ORGOrgIAMPolicyWriteModel) *domain.OrgIAMPolicy {
|
||||
return &domain.OrgIAMPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
||||
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
|
||||
}
|
||||
}
|
||||
|
||||
func orgWriteModelToPasswordComplexityPolicy(wm *OrgPasswordComplexityPolicyWriteModel) *domain.PasswordComplexityPolicy {
|
||||
return &domain.PasswordComplexityPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.PasswordComplexityPolicyWriteModel.WriteModel),
|
||||
MinLength: wm.MinLength,
|
||||
HasLowercase: wm.HasLowercase,
|
||||
HasUppercase: wm.HasUppercase,
|
||||
HasNumber: wm.HasNumber,
|
||||
HasSymbol: wm.HasSymbol,
|
||||
}
|
||||
}
|
||||
|
||||
func orgDomainWriteModelToOrgDomain(wm *OrgDomainWriteModel) *domain.OrgDomain {
|
||||
return &domain.OrgDomain{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
Domain: wm.Domain,
|
||||
Primary: wm.Primary,
|
||||
Verified: wm.Verified,
|
||||
ValidationType: wm.ValidationType,
|
||||
ValidationCode: wm.ValidationCode,
|
||||
}
|
||||
}
|
@@ -1,193 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
http_utils "github.com/caos/zitadel/internal/api/http"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) (*domain.OrgDomain, error) {
|
||||
domainWriteModel := NewOrgDomainWriteModel(orgDomain.AggregateID, orgDomain.Domain)
|
||||
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
|
||||
events, err := r.addOrgDomain(ctx, orgAgg, domainWriteModel, orgDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(domainWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orgDomainWriteModelToOrgDomain(domainWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) GenerateOrgDomainValidation(ctx context.Context, orgDomain *domain.OrgDomain) (token, url string, err error) {
|
||||
if orgDomain == nil || !orgDomain.IsValid() {
|
||||
return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-R24hb", "Errors.Org.InvalidDomain")
|
||||
}
|
||||
checkType, ok := orgDomain.ValidationType.CheckType()
|
||||
if !ok {
|
||||
return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-Gsw31", "Errors.Org.DomainVerificationTypeInvalid")
|
||||
}
|
||||
domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
if domainWriteModel.State != domain.OrgDomainStateActive {
|
||||
return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-AGD31", "Errors.Org.DomainNotOnOrg")
|
||||
}
|
||||
if domainWriteModel.Verified {
|
||||
return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-HGw21", "Errors.Org.DomainAlreadyVerified")
|
||||
}
|
||||
token, err = orgDomain.GenerateVerificationCode(r.domainVerificationGenerator)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
url, err = http_utils.TokenUrl(orgDomain.Domain, token, checkType)
|
||||
if err != nil {
|
||||
return "", "", caos_errs.ThrowPreconditionFailed(err, "ORG-Bae21", "Errors.Org.DomainVerificationTypeInvalid")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(
|
||||
ctx,
|
||||
org.NewDomainVerificationAddedEvent(ctx, orgAgg, orgDomain.Domain, orgDomain.ValidationType, orgDomain.ValidationCode))
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return token, url, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ValidateOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain, claimedUserIDs ...string) error {
|
||||
if orgDomain == nil || !orgDomain.IsValid() {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-R24hb", "Errors.Org.InvalidDomain")
|
||||
}
|
||||
domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if domainWriteModel.State != domain.OrgDomainStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-Sjdi3", "Errors.Org.DomainNotOnOrg")
|
||||
}
|
||||
if domainWriteModel.Verified {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-HGw21", "Errors.Org.DomainAlreadyVerified")
|
||||
}
|
||||
if domainWriteModel.ValidationCode == nil || domainWriteModel.ValidationType == domain.OrgDomainValidationTypeUnspecified {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-SFBB3", "Errors.Org.DomainVerificationMissing")
|
||||
}
|
||||
|
||||
validationCode, err := crypto.DecryptString(domainWriteModel.ValidationCode, r.domainVerificationAlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
checkType, _ := domainWriteModel.ValidationType.CheckType()
|
||||
err = r.domainVerificationValidator(domainWriteModel.Domain, validationCode, validationCode, checkType)
|
||||
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
|
||||
var events []eventstore.EventPusher
|
||||
if err == nil {
|
||||
events = append(events, org.NewDomainVerifiedEvent(ctx, orgAgg, orgDomain.Domain))
|
||||
|
||||
for _, userID := range claimedUserIDs {
|
||||
userEvents, _, err := r.userDomainClaimed(ctx, userID)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-5m8fs", "userid", userID).WithError(err).Warn("could not claim user")
|
||||
continue
|
||||
}
|
||||
events = append(events, userEvents...)
|
||||
}
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
events = append(events, org.NewDomainVerificationFailedEvent(ctx, orgAgg, orgDomain.Domain))
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
logging.LogWithFields("ORG-dhTE", "orgID", orgAgg.ID, "domain", orgDomain.Domain).OnError(err).Error("NewDomainVerificationFailedEvent push failed")
|
||||
return caos_errs.ThrowInvalidArgument(err, "ORG-GH3s", "Errors.Org.DomainVerificationFailed")
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetPrimaryOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) error {
|
||||
if orgDomain == nil || !orgDomain.IsValid() {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-SsDG2", "Errors.Org.InvalidDomain")
|
||||
}
|
||||
domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if domainWriteModel.State != domain.OrgDomainStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-GDfA3", "Errors.Org.DomainNotOnOrg")
|
||||
}
|
||||
if !domainWriteModel.Verified {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-Ggd32", "Errors.Org.DomainNotVerified")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewDomainPrimarySetEvent(ctx, orgAgg, orgDomain.Domain))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) error {
|
||||
if orgDomain == nil || !orgDomain.IsValid() {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-SJsK3", "Errors.Org.InvalidDomain")
|
||||
}
|
||||
domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if domainWriteModel.State != domain.OrgDomainStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-GDfA3", "Errors.Org.DomainNotOnOrg")
|
||||
}
|
||||
if domainWriteModel.Primary {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "ORG-Sjdi3", "Errors.Org.PrimaryDomainNotDeletable")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewDomainRemovedEvent(ctx, orgAgg, orgDomain.Domain))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrgDomain(ctx context.Context, orgAgg *eventstore.Aggregate, addedDomain *OrgDomainWriteModel, orgDomain *domain.OrgDomain, claimedUserIDs ...string) ([]eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedDomain.State == domain.OrgDomainStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMA-Bd2jj", "Errors.Org.Domain.AlreadyExists")
|
||||
}
|
||||
|
||||
events := []eventstore.EventPusher{
|
||||
org.NewDomainAddedEvent(ctx, orgAgg, orgDomain.Domain),
|
||||
}
|
||||
|
||||
if orgDomain.Verified {
|
||||
events = append(events, org.NewDomainVerifiedEvent(ctx, orgAgg, orgDomain.Domain))
|
||||
for _, userID := range claimedUserIDs {
|
||||
userEvents, _, err := r.userDomainClaimed(ctx, userID)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-nn8Jf", "userid", userID).WithError(err).Warn("could not claim user")
|
||||
continue
|
||||
}
|
||||
events = append(events, userEvents...)
|
||||
}
|
||||
}
|
||||
if orgDomain.Primary {
|
||||
events = append(events, org.NewDomainPrimarySetEvent(ctx, orgAgg, orgDomain.Domain))
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getOrgDomainWriteModel(ctx context.Context, orgID, domain string) (*OrgDomainWriteModel, error) {
|
||||
domainWriteModel := NewOrgDomainWriteModel(orgID, domain)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, domainWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return domainWriteModel, nil
|
||||
}
|
@@ -1,99 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgDomainWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Domain string
|
||||
ValidationType domain.OrgDomainValidationType
|
||||
ValidationCode *crypto.CryptoValue
|
||||
Primary bool
|
||||
Verified bool
|
||||
|
||||
State domain.OrgDomainState
|
||||
}
|
||||
|
||||
func NewOrgDomainWriteModel(orgID string, domain string) *OrgDomainWriteModel {
|
||||
return &OrgDomainWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
Domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgDomainWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.DomainAddedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainVerificationAddedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainVerificationFailedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainVerifiedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainPrimarySetEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainRemovedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgDomainWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *org.DomainAddedEvent:
|
||||
wm.Domain = e.Domain
|
||||
wm.State = domain.OrgDomainStateActive
|
||||
case *org.DomainVerificationAddedEvent:
|
||||
wm.ValidationType = e.ValidationType
|
||||
wm.ValidationCode = e.ValidationCode
|
||||
case *org.DomainVerificationFailedEvent:
|
||||
//TODO: not handled in v1
|
||||
case *org.DomainVerifiedEvent:
|
||||
wm.Verified = true
|
||||
case *org.DomainPrimarySetEvent:
|
||||
wm.Primary = e.Domain == wm.Domain
|
||||
case *org.DomainRemovedEvent:
|
||||
wm.State = domain.OrgDomainStateRemoved
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wm *OrgDomainWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.OrgDomainAddedEventType,
|
||||
org.OrgDomainVerifiedEventType,
|
||||
org.OrgDomainVerificationAddedEventType,
|
||||
org.OrgDomainVerifiedEventType,
|
||||
org.OrgDomainPrimarySetEventType,
|
||||
org.OrgDomainRemovedEventType)
|
||||
}
|
@@ -1,157 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
org_repo "github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
|
||||
if config.OIDCConfig == nil {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "Org-eUpQU", "Errors.idp.config.notset")
|
||||
}
|
||||
|
||||
idpConfigID, err := r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedConfig := NewOrgIDPConfigWriteModel(idpConfigID, config.AggregateID)
|
||||
|
||||
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.idpConfigSecretCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedConfig.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
org_repo.NewIDPConfigAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
idpConfigID,
|
||||
config.Name,
|
||||
config.Type,
|
||||
config.StylingType,
|
||||
),
|
||||
org_repo.NewIDPOIDCConfigAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
config.OIDCConfig.ClientID,
|
||||
idpConfigID,
|
||||
config.OIDCConfig.Issuer,
|
||||
clientSecret,
|
||||
config.OIDCConfig.IDPDisplayNameMapping,
|
||||
config.OIDCConfig.UsernameMapping,
|
||||
config.OIDCConfig.Scopes...),
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedConfig, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPConfig(&addedConfig.IDPConfigWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
|
||||
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, config.IDPConfigID, config.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-4M9so", "Errors.Org.IDPConfig.NotExisting")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
changedEvent, hasChanged := existingIDP.NewChangedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
config.IDPConfigID,
|
||||
config.Name,
|
||||
config.StylingType)
|
||||
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingIDP, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPConfig(&existingIDP.IDPConfigWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) DeactivateIDPConfig(ctx context.Context, idpID, orgID string) error {
|
||||
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, idpID, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingIDP.State != domain.IDPConfigStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "Org-4M9so", "Errors.Org.IDPConfig.NotActive")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org_repo.NewIDPConfigDeactivatedEvent(ctx, orgAgg, idpID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) ReactivateIDPConfig(ctx context.Context, idpID, orgID string) error {
|
||||
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, idpID, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingIDP.State != domain.IDPConfigStateInactive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "Org-5Mo0d", "Errors.Org.IDPConfig.NotInactive")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org_repo.NewIDPConfigReactivatedEvent(ctx, orgAgg, idpID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveIDPConfig(ctx context.Context, idpID, orgID string, cascadeRemoveProvider bool, cascadeExternalIDPs ...*domain.ExternalIDP) error {
|
||||
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, idpID, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-Yx9vd", "Errors.Org.IDPConfig.NotExisting")
|
||||
}
|
||||
if existingIDP.State != domain.IDPConfigStateInactive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "Org-5Mo0d", "Errors.Org.IDPConfig.NotInactive")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
org_repo.NewIDPConfigRemovedEvent(ctx, orgAgg, idpID, existingIDP.Name),
|
||||
}
|
||||
|
||||
if cascadeRemoveProvider {
|
||||
removeIDPEvents := r.removeIDPProviderFromLoginPolicy(ctx, orgAgg, idpID, true, cascadeExternalIDPs...)
|
||||
events = append(events, removeIDPEvents...)
|
||||
}
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) orgIDPConfigWriteModelByID(ctx context.Context, idpID, orgID string) (policy *OrgIDPConfigWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewOrgIDPConfigWriteModel(idpID, orgID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,118 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgIDPConfigWriteModel struct {
|
||||
IDPConfigWriteModel
|
||||
}
|
||||
|
||||
func NewOrgIDPConfigWriteModel(configID, orgID string) *OrgIDPConfigWriteModel {
|
||||
return &OrgIDPConfigWriteModel{
|
||||
IDPConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
ConfigID: configID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgIDPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.IDPConfigAddedEventType,
|
||||
org.IDPConfigChangedEventType,
|
||||
org.IDPConfigDeactivatedEventType,
|
||||
org.IDPConfigReactivatedEventType,
|
||||
org.IDPConfigRemovedEventType,
|
||||
org.IDPOIDCConfigAddedEventType,
|
||||
org.IDPOIDCConfigChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *OrgIDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.IDPConfigAddedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigAddedEvent)
|
||||
case *org.IDPConfigChangedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigChangedEvent)
|
||||
case *org.IDPConfigDeactivatedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
|
||||
case *org.IDPConfigReactivatedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
|
||||
case *org.IDPConfigRemovedEvent:
|
||||
if wm.ConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
|
||||
case *org.IDPOIDCConfigAddedEvent:
|
||||
if wm.ConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
|
||||
case *org.IDPOIDCConfigChangedEvent:
|
||||
if wm.ConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgIDPConfigWriteModel) Reduce() error {
|
||||
return wm.IDPConfigWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventReader) error {
|
||||
wm.AppendEvents(events...)
|
||||
return wm.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgIDPConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
configID,
|
||||
name string,
|
||||
stylingType domain.IDPConfigStylingType,
|
||||
) (*org.IDPConfigChangedEvent, bool) {
|
||||
|
||||
changes := make([]idpconfig.IDPConfigChanges, 0)
|
||||
oldName := ""
|
||||
if wm.Name != name {
|
||||
oldName = wm.Name
|
||||
changes = append(changes, idpconfig.ChangeName(name))
|
||||
}
|
||||
if stylingType.Valid() && wm.StylingType != stylingType {
|
||||
changes = append(changes, idpconfig.ChangeStyleType(stylingType))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changeEvent, err := org.NewIDPConfigChangedEvent(ctx, aggregate, configID, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changeEvent, true
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
func (r *CommandSide) ChangeIDPOIDCConfig(ctx context.Context, config *domain.OIDCIDPConfig) (*domain.OIDCIDPConfig, error) {
|
||||
existingConfig := NewOrgIDPOIDCConfigWriteModel(config.IDPConfigID, config.AggregateID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existingConfig.State == domain.IDPConfigStateRemoved || existingConfig.State == domain.IDPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-67J9d", "Errors.Org.IDPConfig.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingConfig.WriteModel)
|
||||
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
config.IDPConfigID,
|
||||
config.ClientID,
|
||||
config.Issuer,
|
||||
config.ClientSecretString,
|
||||
r.idpConfigSecretCrypto,
|
||||
config.IDPDisplayNameMapping,
|
||||
config.UsernameMapping,
|
||||
config.Scopes...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingConfig, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToIDPOIDCConfig(&existingConfig.OIDCConfigWriteModel), nil
|
||||
}
|
@@ -1,129 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type IDPOIDCConfigWriteModel struct {
|
||||
OIDCConfigWriteModel
|
||||
}
|
||||
|
||||
func NewOrgIDPOIDCConfigWriteModel(idpConfigID, orgID string) *IDPOIDCConfigWriteModel {
|
||||
return &IDPOIDCConfigWriteModel{
|
||||
OIDCConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
IDPConfigID: idpConfigID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.IDPOIDCConfigAddedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
|
||||
case *org.IDPOIDCConfigChangedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
|
||||
case *org.IDPConfigReactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
|
||||
case *org.IDPConfigDeactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
|
||||
case *org.IDPConfigRemovedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
|
||||
default:
|
||||
wm.OIDCConfigWriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IDPOIDCConfigWriteModel) Reduce() error {
|
||||
if err := wm.OIDCConfigWriteModel.Reduce(); err != nil {
|
||||
return err
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IDPOIDCConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.IDPOIDCConfigAddedEventType,
|
||||
org.IDPOIDCConfigChangedEventType,
|
||||
org.IDPConfigReactivatedEventType,
|
||||
org.IDPConfigDeactivatedEventType,
|
||||
org.IDPConfigRemovedEventType)
|
||||
}
|
||||
|
||||
func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
idpConfigID,
|
||||
clientID,
|
||||
issuer,
|
||||
clientSecretString string,
|
||||
secretCrypto crypto.Crypto,
|
||||
idpDisplayNameMapping,
|
||||
userNameMapping domain.OIDCMappingField,
|
||||
scopes ...string,
|
||||
) (*org.IDPOIDCConfigChangedEvent, bool, error) {
|
||||
|
||||
changes := make([]idpconfig.OIDCConfigChanges, 0)
|
||||
var clientSecret *crypto.CryptoValue
|
||||
var err error
|
||||
if clientSecretString != "" {
|
||||
clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
changes = append(changes, idpconfig.ChangeClientSecret(clientSecret))
|
||||
}
|
||||
if wm.ClientID != clientID {
|
||||
changes = append(changes, idpconfig.ChangeClientID(clientID))
|
||||
}
|
||||
if wm.Issuer != issuer {
|
||||
changes = append(changes, idpconfig.ChangeIssuer(issuer))
|
||||
}
|
||||
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
|
||||
changes = append(changes, idpconfig.ChangeIDPDisplayNameMapping(idpDisplayNameMapping))
|
||||
}
|
||||
if userNameMapping.Valid() && wm.UserNameMapping != userNameMapping {
|
||||
changes = append(changes, idpconfig.ChangeUserNameMapping(userNameMapping))
|
||||
}
|
||||
if reflect.DeepEqual(wm.Scopes, scopes) {
|
||||
changes = append(changes, idpconfig.ChangeScopes(scopes))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := org.NewIDPOIDCConfigChangedEvent(ctx, aggregate, idpConfigID, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddOrgMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
addedMember := NewOrgMemberWriteModel(member.AggregateID, member.UserID)
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedMember.WriteModel)
|
||||
event, err := r.addOrgMember(ctx, orgAgg, addedMember, member)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrgMember(ctx context.Context, orgAgg *eventstore.Aggregate, addedMember *OrgMemberWriteModel, member *domain.Member) (eventstore.EventPusher, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-W8m4l", "Errors.Org.MemberInvalid")
|
||||
}
|
||||
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedMember)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedMember.State == domain.MemberStateActive {
|
||||
return nil, errors.ThrowAlreadyExists(nil, "Org-PtXi1", "Errors.Org.Member.AlreadyExists")
|
||||
}
|
||||
|
||||
return org.NewMemberAddedEvent(ctx, orgAgg, member.UserID, member.Roles...), nil
|
||||
}
|
||||
|
||||
//ChangeOrgMember updates an existing member
|
||||
func (r *CommandSide) ChangeOrgMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-LiaZi", "Errors.Org.MemberInvalid")
|
||||
}
|
||||
|
||||
existingMember, err := r.orgMemberWriteModelByID(ctx, member.AggregateID, member.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(existingMember.Roles, member.Roles) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-LiaZi", "Errors.Org.Member.RolesNotChanged")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingMember.MemberWriteModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, org.NewMemberChangedEvent(ctx, orgAgg, member.UserID, member.Roles...))
|
||||
err = AppendAndReduce(existingMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveOrgMember(ctx context.Context, orgID, userID string) error {
|
||||
m, err := r.orgMemberWriteModelByID(ctx, orgID, userID)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewMemberRemovedEvent(ctx, orgAgg, userID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) orgMemberWriteModelByID(ctx context.Context, orgID, userID string) (member *OrgMemberWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewOrgMemberWriteModel(orgID, userID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if writeModel.State == domain.MemberStateUnspecified || writeModel.State == domain.MemberStateRemoved {
|
||||
return nil, errors.ThrowNotFound(nil, "Org-D8JxR", "Errors.NotFound")
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,58 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgMemberWriteModel struct {
|
||||
MemberWriteModel
|
||||
}
|
||||
|
||||
func NewOrgMemberWriteModel(orgID, userID string) *OrgMemberWriteModel {
|
||||
return &OrgMemberWriteModel{
|
||||
MemberWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
UserID: userID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.MemberAddedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberAddedEvent)
|
||||
case *org.MemberChangedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberChangedEvent)
|
||||
case *org.MemberRemovedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMemberWriteModel) Reduce() error {
|
||||
return wm.MemberWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.MemberWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.MemberAddedEventType,
|
||||
org.MemberChangedEventType,
|
||||
org.MemberRemovedEventType)
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Name string
|
||||
State domain.OrgState
|
||||
PrimaryDomain string
|
||||
}
|
||||
|
||||
func NewOrgWriteModel(orgID string) *OrgWriteModel {
|
||||
return &OrgWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *org.OrgAddedEvent:
|
||||
wm.Name = e.Name
|
||||
wm.State = domain.OrgStateActive
|
||||
case *org.OrgChangedEvent:
|
||||
wm.Name = e.Name
|
||||
case *org.DomainPrimarySetEvent:
|
||||
wm.PrimaryDomain = e.Domain
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wm *OrgWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.OrgAddedEventType,
|
||||
org.OrgChangedEventType,
|
||||
org.OrgDomainPrimarySetEventType)
|
||||
}
|
||||
|
||||
func OrgAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
|
||||
return eventstore.AggregateFromWriteModel(wm, org.AggregateType, org.AggregateVersion)
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddLabelPolicy(ctx context.Context, resourceOwner string, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) {
|
||||
addedPolicy := NewOrgLabelPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-2B0ps", "Errors.Org.LabelPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, org.NewLabelPolicyAddedEvent(ctx, orgAgg, policy.PrimaryColor, policy.SecondaryColor))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLabelPolicy(&addedPolicy.LabelPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeLabelPolicy(ctx context.Context, resourceOwner string, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) {
|
||||
existingPolicy := NewOrgLabelPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-0K9dq", "Errors.Org.LabelPolicy.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.PrimaryColor, policy.SecondaryColor)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveLabelPolicy(ctx context.Context, orgID string) error {
|
||||
existingPolicy := NewOrgLabelPolicyWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-3M9df", "Errors.Org.LabelPolicy.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewLabelPolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
@@ -1,71 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type OrgLabelPolicyWriteModel struct {
|
||||
LabelPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewOrgLabelPolicyWriteModel(orgID string) *OrgLabelPolicyWriteModel {
|
||||
return &OrgLabelPolicyWriteModel{
|
||||
LabelPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgLabelPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.LabelPolicyAddedEvent:
|
||||
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyAddedEvent)
|
||||
case *org.LabelPolicyChangedEvent:
|
||||
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyChangedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgLabelPolicyWriteModel) Reduce() error {
|
||||
return wm.LabelPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgLabelPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.LabelPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.LabelPolicyAddedEventType,
|
||||
org.LabelPolicyChangedEventType)
|
||||
}
|
||||
|
||||
func (wm *OrgLabelPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
primaryColor,
|
||||
secondaryColor string,
|
||||
) (*org.LabelPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.LabelPolicyChanges, 0)
|
||||
if wm.PrimaryColor != primaryColor {
|
||||
changes = append(changes, policy.ChangePrimaryColor(primaryColor))
|
||||
}
|
||||
if wm.SecondaryColor != secondaryColor {
|
||||
changes = append(changes, policy.ChangeSecondaryColor(secondaryColor))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewLabelPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,208 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddLoginPolicy(ctx context.Context, resourceOwner string, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
addedPolicy := NewOrgLoginPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-Dgfb2", "Errors.Org.LoginPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(
|
||||
ctx,
|
||||
org.NewLoginPolicyAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
policy.AllowUsernamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.PasswordlessType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLoginPolicy(&addedPolicy.LoginPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeLoginPolicy(ctx context.Context, resourceOwner string, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
existingPolicy := NewOrgLoginPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-M0sif", "Errors.Org.LoginPolicy.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIDP, policy.ForceMFA, policy.PasswordlessType)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-5M9vdd", "Errors.Org.LoginPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLoginPolicy(&existingPolicy.LoginPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveLoginPolicy(ctx context.Context, orgID string) error {
|
||||
existingPolicy := NewOrgLoginPolicyWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-GHB37", "Errors.Org.LoginPolicy.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewLoginPolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddIDPProviderToLoginPolicy(ctx context.Context, resourceOwner string, idpProvider *domain.IDPProvider) (*domain.IDPProvider, error) {
|
||||
idpModel := NewOrgIdentityProviderWriteModel(resourceOwner, idpProvider.IDPConfigID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if idpModel.State == domain.IdentityProviderStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-2B0ps", "Errors.Org.LoginPolicy.IDP.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&idpModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, org.NewIdentityProviderAddedEvent(ctx, orgAgg, idpProvider.IDPConfigID, idpProvider.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(idpModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveIDPProviderFromLoginPolicy(ctx context.Context, resourceOwner string, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.ExternalIDP) error {
|
||||
idpModel := NewOrgIdentityProviderWriteModel(resourceOwner, idpProvider.IDPConfigID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if idpModel.State == domain.IdentityProviderStateUnspecified || idpModel.State == domain.IdentityProviderStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-39fjs", "Errors.Org.LoginPolicy.IDP.NotExisting")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
|
||||
events := r.removeIDPProviderFromLoginPolicy(ctx, orgAgg, idpProvider.IDPConfigID, false, cascadeExternalIDPs...)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) removeIDPProviderFromLoginPolicy(ctx context.Context, orgAgg *eventstore.Aggregate, idpConfigID string, cascade bool, cascadeExternalIDPs ...*domain.ExternalIDP) []eventstore.EventPusher {
|
||||
var events []eventstore.EventPusher
|
||||
if cascade {
|
||||
events = append(events, org.NewIdentityProviderCascadeRemovedEvent(ctx, orgAgg, idpConfigID))
|
||||
} else {
|
||||
events = append(events, org.NewIdentityProviderRemovedEvent(ctx, orgAgg, idpConfigID))
|
||||
}
|
||||
|
||||
for _, idp := range cascadeExternalIDPs {
|
||||
event, err := r.removeHumanExternalIDP(ctx, idp, true)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-n8RRf", "userid", idp.AggregateID, "idpconfigid", idp.IDPConfigID).WithError(err).Warn("could not cascade remove external idp")
|
||||
continue
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddSecondFactorToLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType, orgID string) (domain.SecondFactorType, error) {
|
||||
secondFactorModel := NewOrgSecondFactorWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
|
||||
if err != nil {
|
||||
return domain.SecondFactorTypeUnspecified, err
|
||||
}
|
||||
|
||||
if secondFactorModel.State == domain.FactorStateActive {
|
||||
return domain.SecondFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "Org-2B0ps", "Errors.Org.LoginPolicy.MFA.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
|
||||
|
||||
if _, err = r.eventstore.PushEvents(ctx, org.NewLoginPolicySecondFactorAddedEvent(ctx, orgAgg, secondFactor)); err != nil {
|
||||
return domain.SecondFactorTypeUnspecified, err
|
||||
}
|
||||
|
||||
return secondFactorModel.MFAType, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveSecondFactorFromLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType, orgID string) error {
|
||||
secondFactorModel := NewOrgSecondFactorWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if secondFactorModel.State == domain.FactorStateUnspecified || secondFactorModel.State == domain.FactorStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-3M9od", "Errors.Org.LoginPolicy.MFA.NotExisting")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewLoginPolicySecondFactorRemovedEvent(ctx, orgAgg, secondFactor))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddMultiFactorToLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType, orgID string) (domain.MultiFactorType, error) {
|
||||
multiFactorModel := NewOrgMultiFactorWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
|
||||
if err != nil {
|
||||
return domain.MultiFactorTypeUnspecified, err
|
||||
}
|
||||
if multiFactorModel.State == domain.FactorStateActive {
|
||||
return domain.MultiFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "Org-3M9od", "Errors.Org.LoginPolicy.MFA.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&multiFactorModel.WriteModel)
|
||||
|
||||
if _, err = r.eventstore.PushEvents(ctx, org.NewLoginPolicyMultiFactorAddedEvent(ctx, orgAgg, multiFactor)); err != nil {
|
||||
return domain.MultiFactorTypeUnspecified, err
|
||||
}
|
||||
|
||||
return multiFactorModel.MFAType, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveMultiFactorFromLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType, orgID string) error {
|
||||
multiFactorModel := NewOrgMultiFactorWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if multiFactorModel.State == domain.FactorStateUnspecified || multiFactorModel.State == domain.FactorStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-3M9df", "Errors.Org.LoginPolicy.MFA.NotExisting")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewLoginPolicyMultiFactorRemovedEvent(ctx, orgAgg, multiFactor))
|
||||
return err
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgSecondFactorWriteModel struct {
|
||||
SecondFactorWriteModel
|
||||
}
|
||||
|
||||
func NewOrgSecondFactorWriteModel(orgID string) *OrgSecondFactorWriteModel {
|
||||
return &OrgSecondFactorWriteModel{
|
||||
SecondFactorWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgSecondFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.LoginPolicySecondFactorAddedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.SecondFactorAddedEvent)
|
||||
case *org.LoginPolicySecondFactorRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.SecondFactorRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgSecondFactorWriteModel) Reduce() error {
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgSecondFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.WriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.LoginPolicySecondFactorAddedEventType,
|
||||
org.LoginPolicySecondFactorRemovedEventType)
|
||||
}
|
||||
|
||||
type OrgMultiFactorWriteModel struct {
|
||||
MultiFactoryWriteModel
|
||||
}
|
||||
|
||||
func NewOrgMultiFactorWriteModel(orgID string) *OrgMultiFactorWriteModel {
|
||||
return &OrgMultiFactorWriteModel{
|
||||
MultiFactoryWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMultiFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.LoginPolicyMultiFactorAddedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.MultiFactorAddedEvent)
|
||||
case *org.LoginPolicyMultiFactorRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(&e.MultiFactorRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMultiFactorWriteModel) Reduce() error {
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgMultiFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.WriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.LoginPolicyMultiFactorAddedEventType,
|
||||
org.LoginPolicyMultiFactorRemovedEventType)
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
type OrgIdentityProviderWriteModel struct {
|
||||
IdentityProviderWriteModel
|
||||
}
|
||||
|
||||
func NewOrgIdentityProviderWriteModel(orgID, idpConfigID string) *OrgIdentityProviderWriteModel {
|
||||
return &OrgIdentityProviderWriteModel{
|
||||
IdentityProviderWriteModel: IdentityProviderWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
IDPConfigID: idpConfigID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgIdentityProviderWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.IdentityProviderAddedEvent:
|
||||
if e.IDPConfigID != wm.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderAddedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgIdentityProviderWriteModel) Reduce() error {
|
||||
return wm.IdentityProviderWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgIdentityProviderWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner)
|
||||
}
|
@@ -1,92 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type OrgLoginPolicyWriteModel struct {
|
||||
LoginPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewOrgLoginPolicyWriteModel(orgID string) *OrgLoginPolicyWriteModel {
|
||||
return &OrgLoginPolicyWriteModel{
|
||||
LoginPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgLoginPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.LoginPolicyAddedEvent:
|
||||
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyAddedEvent)
|
||||
case *org.LoginPolicyChangedEvent:
|
||||
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyChangedEvent)
|
||||
case *org.LoginPolicyRemovedEvent:
|
||||
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgLoginPolicyWriteModel) IsValid() bool {
|
||||
return wm.AggregateID != ""
|
||||
}
|
||||
|
||||
func (wm *OrgLoginPolicyWriteModel) Reduce() error {
|
||||
return wm.LoginPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgLoginPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.LoginPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.LoginPolicyAddedEventType,
|
||||
org.LoginPolicyChangedEventType,
|
||||
org.LoginPolicyRemovedEventType)
|
||||
}
|
||||
|
||||
func (wm *OrgLoginPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
allowUsernamePassword,
|
||||
allowRegister,
|
||||
allowExternalIDP,
|
||||
forceMFA bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
) (*org.LoginPolicyChangedEvent, bool) {
|
||||
|
||||
changes := make([]policy.LoginPolicyChanges, 0)
|
||||
if wm.AllowUserNamePassword != allowUsernamePassword {
|
||||
changes = append(changes, policy.ChangeAllowUserNamePassword(allowUsernamePassword))
|
||||
}
|
||||
if wm.AllowRegister != allowRegister {
|
||||
changes = append(changes, policy.ChangeAllowRegister(allowRegister))
|
||||
}
|
||||
if wm.AllowExternalIDP != allowExternalIDP {
|
||||
changes = append(changes, policy.ChangeAllowExternalIDP(allowExternalIDP))
|
||||
}
|
||||
if wm.ForceMFA != forceMFA {
|
||||
changes = append(changes, policy.ChangeForceMFA(forceMFA))
|
||||
}
|
||||
if passwordlessType.Valid() && wm.PasswordlessType != passwordlessType {
|
||||
changes = append(changes, policy.ChangePasswordlessType(passwordlessType))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewLoginPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddMailTemplate(ctx context.Context, resourceOwner string, policy *domain.MailTemplate) (*domain.MailTemplate, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-3m9fs", "Errors.Org.MailTemplate.Invalid")
|
||||
}
|
||||
addedPolicy := NewOrgMailTemplateWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-9kufs", "Errors.Org.MailTemplate.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.MailTemplateWriteModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, org.NewMailTemplateAddedEvent(ctx, orgAgg, policy.Template))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToMailTemplate(&addedPolicy.MailTemplateWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeMailTemplate(ctx context.Context, resourceOwner string, policy *domain.MailTemplate) (*domain.MailTemplate, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-9f9ds", "Errors.Org.MailTemplate.Invalid")
|
||||
}
|
||||
existingPolicy := NewOrgMailTemplateWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-5m9ie", "Errors.Org.MailTemplate.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.MailTemplateWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.Template)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.MailTemplate.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToMailTemplate(&existingPolicy.MailTemplateWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveMailTemplate(ctx context.Context, orgID string) error {
|
||||
existingPolicy := NewOrgMailTemplateWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-3b8Jf", "Errors.Org.MailTemplate.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewMailTemplateRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
@@ -1,75 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type OrgMailTemplateWriteModel struct {
|
||||
MailTemplateWriteModel
|
||||
}
|
||||
|
||||
func NewOrgMailTemplateWriteModel(orgID string) *OrgMailTemplateWriteModel {
|
||||
return &OrgMailTemplateWriteModel{
|
||||
MailTemplateWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMailTemplateWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.MailTemplateAddedEvent:
|
||||
wm.MailTemplateWriteModel.AppendEvents(&e.MailTemplateAddedEvent)
|
||||
case *org.MailTemplateChangedEvent:
|
||||
wm.MailTemplateWriteModel.AppendEvents(&e.MailTemplateChangedEvent)
|
||||
case *org.MailTemplateRemovedEvent:
|
||||
wm.MailTemplateWriteModel.AppendEvents(&e.MailTemplateRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMailTemplateWriteModel) Reduce() error {
|
||||
return wm.MailTemplateWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgMailTemplateWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.MailTemplateWriteModel.AggregateID).
|
||||
EventTypes(
|
||||
org.MailTemplateAddedEventType,
|
||||
org.MailTemplateChangedEventType,
|
||||
org.MailTemplateRemovedEventType)
|
||||
|
||||
if wm.ResourceOwner != "" {
|
||||
query.ResourceOwner(wm.ResourceOwner)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func (wm *OrgMailTemplateWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
template []byte,
|
||||
) (*org.MailTemplateChangedEvent, bool) {
|
||||
changes := make([]policy.MailTemplateChanges, 0)
|
||||
if !reflect.DeepEqual(wm.Template, template) {
|
||||
changes = append(changes, policy.ChangeTemplate(template))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewMailTemplateChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,102 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddMailText(ctx context.Context, resourceOwner string, mailText *domain.MailText) (*domain.MailText, error) {
|
||||
if !mailText.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4778u", "Errors.Org.MailText.Invalid")
|
||||
}
|
||||
addedPolicy := NewOrgMailTextWriteModel(resourceOwner, mailText.MailTextType, mailText.Language)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-9kufs", "Errors.Org.MailText.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.MailTextWriteModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(
|
||||
ctx,
|
||||
org.NewMailTextAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
mailText.MailTextType,
|
||||
mailText.Language,
|
||||
mailText.Title,
|
||||
mailText.PreHeader,
|
||||
mailText.Subject,
|
||||
mailText.Greeting,
|
||||
mailText.Text,
|
||||
mailText.ButtonText))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToMailText(&addedPolicy.MailTextWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeMailText(ctx context.Context, resourceOwner string, mailText *domain.MailText) (*domain.MailText, error) {
|
||||
if !mailText.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-3m9fs", "Errors.Org.MailText.Invalid")
|
||||
}
|
||||
existingPolicy := NewOrgMailTextWriteModel(resourceOwner, mailText.MailTextType, mailText.Language)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-3n8fM", "Errors.Org.MailText.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.MailTextWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
mailText.MailTextType,
|
||||
mailText.Language,
|
||||
mailText.Title,
|
||||
mailText.PreHeader,
|
||||
mailText.Subject,
|
||||
mailText.Greeting,
|
||||
mailText.Text,
|
||||
mailText.ButtonText)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-2n9fs", "Errors.Org.MailText.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToMailText(&existingPolicy.MailTextWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveMailText(ctx context.Context, resourceOwner, mailTextType, language string) error {
|
||||
existingPolicy := NewOrgMailTextWriteModel(resourceOwner, mailTextType, language)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-3b8Jf", "Errors.Org.MailText.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewMailTextRemovedEvent(ctx, orgAgg, mailTextType, language))
|
||||
return err
|
||||
}
|
@@ -1,95 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type OrgMailTextWriteModel struct {
|
||||
MailTextWriteModel
|
||||
}
|
||||
|
||||
func NewOrgMailTextWriteModel(orgID, mailTextType, language string) *OrgMailTextWriteModel {
|
||||
return &OrgMailTextWriteModel{
|
||||
MailTextWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
MailTextType: mailTextType,
|
||||
Language: language,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMailTextWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.MailTextAddedEvent:
|
||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextAddedEvent)
|
||||
case *org.MailTextChangedEvent:
|
||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextChangedEvent)
|
||||
case *org.MailTextRemovedEvent:
|
||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMailTextWriteModel) Reduce() error {
|
||||
return wm.MailTextWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgMailTextWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.MailTextWriteModel.AggregateID).
|
||||
EventTypes(org.MailTextAddedEventType,
|
||||
org.MailTextChangedEventType,
|
||||
org.MailTextRemovedEventType)
|
||||
if wm.ResourceOwner != "" {
|
||||
query.ResourceOwner(wm.ResourceOwner)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func (wm *OrgMailTextWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
mailTextType,
|
||||
language,
|
||||
title,
|
||||
preHeader,
|
||||
subject,
|
||||
greeting,
|
||||
text,
|
||||
buttonText string,
|
||||
) (*org.MailTextChangedEvent, bool) {
|
||||
changes := make([]policy.MailTextChanges, 0)
|
||||
if wm.Title != title {
|
||||
changes = append(changes, policy.ChangeTitle(title))
|
||||
}
|
||||
if wm.PreHeader != preHeader {
|
||||
changes = append(changes, policy.ChangePreHeader(preHeader))
|
||||
}
|
||||
if wm.Subject != subject {
|
||||
changes = append(changes, policy.ChangeSubject(subject))
|
||||
}
|
||||
if wm.Greeting != greeting {
|
||||
changes = append(changes, policy.ChangeGreeting(greeting))
|
||||
}
|
||||
if wm.Text != text {
|
||||
changes = append(changes, policy.ChangeText(text))
|
||||
}
|
||||
if wm.ButtonText != buttonText {
|
||||
changes = append(changes, policy.ChangeButtonText(buttonText))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewMailTextChangedEvent(ctx, aggregate, mailTextType, language, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,102 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, resourceOwner string, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||
addedPolicy := NewORGOrgIAMPolicyWriteModel(resourceOwner)
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
event, err := r.addOrgIAMPolicy(ctx, orgAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orgWriteModelToOrgIAMPolicy(addedPolicy), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrgIAMPolicy(ctx context.Context, orgAgg *eventstore.Aggregate, addedPolicy *ORGOrgIAMPolicyWriteModel, policy *domain.OrgIAMPolicy) (eventstore.EventPusher, error) {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-1M8ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
||||
}
|
||||
return org.NewOrgIAMPolicyAddedEvent(ctx, orgAgg, policy.UserLoginMustBeDomain), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, resourceOwner string, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "ORG-2N9sd", "Errors.Org.OrgIAMPolicy.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.UserLoginMustBeDomain)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orgWriteModelToOrgIAMPolicy(existingPolicy), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveOrgIAMPolicy(ctx context.Context, orgID string) error {
|
||||
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "ORG-Dvsh3", "Errors.Org.OrgIAMPolicy.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewOrgIAMPolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) getOrgIAMPolicy(ctx context.Context, orgID string) (*domain.OrgIAMPolicy, error) {
|
||||
policy, err := r.orgIAMPolicyWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if policy.State == domain.PolicyStateActive {
|
||||
return orgWriteModelToOrgIAMPolicy(policy), nil
|
||||
}
|
||||
return r.getDefaultOrgIAMPolicy(ctx)
|
||||
}
|
||||
|
||||
func (r *CommandSide) orgIAMPolicyWriteModelByID(ctx context.Context, orgID string) (policy *ORGOrgIAMPolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewORGOrgIAMPolicyWriteModel(orgID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type ORGOrgIAMPolicyWriteModel struct {
|
||||
PolicyOrgIAMWriteModel
|
||||
}
|
||||
|
||||
func NewORGOrgIAMPolicyWriteModel(orgID string) *ORGOrgIAMPolicyWriteModel {
|
||||
return &ORGOrgIAMPolicyWriteModel{
|
||||
PolicyOrgIAMWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ORGOrgIAMPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.OrgIAMPolicyAddedEvent:
|
||||
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyAddedEvent)
|
||||
case *org.OrgIAMPolicyChangedEvent:
|
||||
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyChangedEvent)
|
||||
case *org.OrgIAMPolicyRemovedEvent:
|
||||
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ORGOrgIAMPolicyWriteModel) Reduce() error {
|
||||
return wm.PolicyOrgIAMWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ORGOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.PolicyOrgIAMWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(org.OrgIAMPolicyAddedEventType,
|
||||
org.OrgIAMPolicyChangedEventType,
|
||||
org.OrgIAMPolicyRemovedEventType)
|
||||
}
|
||||
|
||||
func (wm *ORGOrgIAMPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
userLoginMustBeDomain bool) (*org.OrgIAMPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.OrgIAMPolicyChanges, 0)
|
||||
if wm.UserLoginMustBeDomain != userLoginMustBeDomain {
|
||||
changes = append(changes, policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewOrgIAMPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddPasswordAgePolicy(ctx context.Context, resourceOwner string, policy *domain.PasswordAgePolicy) (*domain.PasswordAgePolicy, error) {
|
||||
addedPolicy := NewOrgPasswordAgePolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-Lk0dS", "Errors.Org.PasswordAgePolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, org.NewPasswordAgePolicyAddedEvent(ctx, orgAgg, policy.ExpireWarnDays, policy.MaxAgeDays))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordAgePolicy(&addedPolicy.PasswordAgePolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangePasswordAgePolicy(ctx context.Context, resourceOwner string, policy *domain.PasswordAgePolicy) (*domain.PasswordAgePolicy, error) {
|
||||
existingPolicy := NewOrgPasswordAgePolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "ORG-0oPew", "Errors.Org.PasswordAgePolicy.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PasswordAgePolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.ExpireWarnDays, policy.MaxAgeDays)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-dsgjR", "Errors.ORg.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordAgePolicy(&existingPolicy.PasswordAgePolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemovePasswordAgePolicy(ctx context.Context, orgID string) error {
|
||||
existingPolicy := NewOrgPasswordAgePolicyWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "ORG-Dgs1g", "Errors.Org.PasswordAgePolicy.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewPasswordAgePolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type OrgPasswordAgePolicyWriteModel struct {
|
||||
PasswordAgePolicyWriteModel
|
||||
}
|
||||
|
||||
func NewOrgPasswordAgePolicyWriteModel(orgID string) *OrgPasswordAgePolicyWriteModel {
|
||||
return &OrgPasswordAgePolicyWriteModel{
|
||||
PasswordAgePolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordAgePolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.PasswordAgePolicyAddedEvent:
|
||||
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyAddedEvent)
|
||||
case *org.PasswordAgePolicyChangedEvent:
|
||||
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyChangedEvent)
|
||||
case *org.PasswordAgePolicyRemovedEvent:
|
||||
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordAgePolicyWriteModel) Reduce() error {
|
||||
return wm.PasswordAgePolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordAgePolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.PasswordAgePolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
org.PasswordAgePolicyAddedEventType,
|
||||
org.PasswordAgePolicyChangedEventType,
|
||||
org.PasswordAgePolicyRemovedEventType)
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordAgePolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
expireWarnDays,
|
||||
maxAgeDays uint64) (*org.PasswordAgePolicyChangedEvent, bool) {
|
||||
changes := make([]policy.PasswordAgePolicyChanges, 0)
|
||||
if wm.ExpireWarnDays != expireWarnDays {
|
||||
changes = append(changes, policy.ChangeExpireWarnDays(expireWarnDays))
|
||||
}
|
||||
if wm.MaxAgeDays != maxAgeDays {
|
||||
changes = append(changes, policy.ChangeMaxAgeDays(maxAgeDays))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewPasswordAgePolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,100 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) getOrgPasswordComplexityPolicy(ctx context.Context, orgID string) (*domain.PasswordComplexityPolicy, error) {
|
||||
policy := NewOrgPasswordComplexityPolicyWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if policy.State == domain.PolicyStateActive {
|
||||
return orgWriteModelToPasswordComplexityPolicy(policy), nil
|
||||
}
|
||||
return r.getDefaultPasswordComplexityPolicy(ctx)
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddPasswordComplexityPolicy(ctx context.Context, resourceOwner string, policy *domain.PasswordComplexityPolicy) (*domain.PasswordComplexityPolicy, error) {
|
||||
if err := policy.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedPolicy := NewOrgPasswordComplexityPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-LdhbS", "Errors.Org.PasswordComplexityPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(
|
||||
ctx,
|
||||
org.NewPasswordComplexityPolicyAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
policy.MinLength,
|
||||
policy.HasLowercase,
|
||||
policy.HasUppercase,
|
||||
policy.HasNumber,
|
||||
policy.HasSymbol))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordComplexityPolicy(&addedPolicy.PasswordComplexityPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangePasswordComplexityPolicy(ctx context.Context, resourceOwner string, policy *domain.PasswordComplexityPolicy) (*domain.PasswordComplexityPolicy, error) {
|
||||
if err := policy.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingPolicy := NewOrgPasswordComplexityPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "ORG-Dgs3g", "Errors.Org.PasswordComplexityPolicy.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-DAs21", "Errors.Org.PasswordComplexityPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordComplexityPolicy(&existingPolicy.PasswordComplexityPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemovePasswordComplexityPolicy(ctx context.Context, orgID string) error {
|
||||
existingPolicy := NewOrgPasswordComplexityPolicyWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "ORG-ADgs2", "Errors.Org.PasswordComplexityPolicy.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewPasswordComplexityPolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
@@ -1,86 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type OrgPasswordComplexityPolicyWriteModel struct {
|
||||
PasswordComplexityPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewOrgPasswordComplexityPolicyWriteModel(orgID string) *OrgPasswordComplexityPolicyWriteModel {
|
||||
return &OrgPasswordComplexityPolicyWriteModel{
|
||||
PasswordComplexityPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordComplexityPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.PasswordComplexityPolicyAddedEvent:
|
||||
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent)
|
||||
case *org.PasswordComplexityPolicyChangedEvent:
|
||||
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent)
|
||||
case *org.PasswordComplexityPolicyRemovedEvent:
|
||||
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordComplexityPolicyWriteModel) Reduce() error {
|
||||
return wm.PasswordComplexityPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordComplexityPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.PasswordComplexityPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(org.PasswordComplexityPolicyAddedEventType,
|
||||
org.PasswordComplexityPolicyChangedEventType,
|
||||
org.PasswordComplexityPolicyRemovedEventType)
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordComplexityPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
minLength uint64,
|
||||
hasLowercase,
|
||||
hasUppercase,
|
||||
hasNumber,
|
||||
hasSymbol bool,
|
||||
) (*org.PasswordComplexityPolicyChangedEvent, bool) {
|
||||
|
||||
changes := make([]policy.PasswordComplexityPolicyChanges, 0)
|
||||
if wm.MinLength != minLength {
|
||||
changes = append(changes, policy.ChangeMinLength(minLength))
|
||||
}
|
||||
if wm.HasLowercase != hasLowercase {
|
||||
changes = append(changes, policy.ChangeHasLowercase(hasLowercase))
|
||||
}
|
||||
if wm.HasUppercase != hasUppercase {
|
||||
changes = append(changes, policy.ChangeHasUppercase(hasUppercase))
|
||||
}
|
||||
if wm.HasNumber != hasNumber {
|
||||
changes = append(changes, policy.ChangeHasNumber(hasNumber))
|
||||
}
|
||||
if wm.HasSymbol != hasSymbol {
|
||||
changes = append(changes, policy.ChangeHasSymbol(hasSymbol))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewPasswordComplexityPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddPasswordLockoutPolicy(ctx context.Context, resourceOwner string, policy *domain.PasswordLockoutPolicy) (*domain.PasswordLockoutPolicy, error) {
|
||||
addedPolicy := NewOrgPasswordLockoutPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-0olDf", "Errors.ORG.PasswordLockoutPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, org.NewPasswordLockoutPolicyAddedEvent(ctx, orgAgg, policy.MaxAttempts, policy.ShowLockOutFailures))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordLockoutPolicy(&addedPolicy.PasswordLockoutPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangePasswordLockoutPolicy(ctx context.Context, resourceOwner string, policy *domain.PasswordLockoutPolicy) (*domain.PasswordLockoutPolicy, error) {
|
||||
existingPolicy := NewOrgPasswordLockoutPolicyWriteModel(resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "ORG-ADfs1", "Errors.Org.PasswordLockoutPolicy.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.MaxAttempts, policy.ShowLockOutFailures)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-4M9vs", "Errors.Org.PasswordLockoutPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToPasswordLockoutPolicy(&existingPolicy.PasswordLockoutPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemovePasswordLockoutPolicy(ctx context.Context, orgID string) error {
|
||||
existingPolicy := NewOrgPasswordLockoutPolicyWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "ORG-D4zuz", "Errors.Org.PasswordLockoutPolicy.NotFound")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, org.NewPasswordLockoutPolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type OrgPasswordLockoutPolicyWriteModel struct {
|
||||
PasswordLockoutPolicyWriteModel
|
||||
}
|
||||
|
||||
func NewOrgPasswordLockoutPolicyWriteModel(orgID string) *OrgPasswordLockoutPolicyWriteModel {
|
||||
return &OrgPasswordLockoutPolicyWriteModel{
|
||||
PasswordLockoutPolicyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordLockoutPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.PasswordLockoutPolicyAddedEvent:
|
||||
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyAddedEvent)
|
||||
case *org.PasswordLockoutPolicyChangedEvent:
|
||||
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyChangedEvent)
|
||||
case *org.PasswordLockoutPolicyRemovedEvent:
|
||||
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordLockoutPolicyWriteModel) Reduce() error {
|
||||
return wm.PasswordLockoutPolicyWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordLockoutPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.PasswordLockoutPolicyWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(org.PasswordLockoutPolicyAddedEventType,
|
||||
org.PasswordLockoutPolicyChangedEventType,
|
||||
org.PasswordLockoutPolicyRemovedEventType)
|
||||
}
|
||||
|
||||
func (wm *OrgPasswordLockoutPolicyWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
maxAttempts uint64,
|
||||
showLockoutFailure bool) (*org.PasswordLockoutPolicyChangedEvent, bool) {
|
||||
changes := make([]policy.PasswordLockoutPolicyChanges, 0)
|
||||
if wm.MaxAttempts != maxAttempts {
|
||||
changes = append(changes, policy.ChangeMaxAttempts(maxAttempts))
|
||||
}
|
||||
if wm.ShowLockOutFailures != showLockoutFailure {
|
||||
changes = append(changes, policy.ChangeShowLockOutFailures(showLockoutFailure))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := org.NewPasswordLockoutPolicyChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type LabelPolicyWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
PrimaryColor string
|
||||
SecondaryColor string
|
||||
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *LabelPolicyWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.LabelPolicyAddedEvent:
|
||||
wm.PrimaryColor = e.PrimaryColor
|
||||
wm.SecondaryColor = e.SecondaryColor
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.LabelPolicyChangedEvent:
|
||||
if e.PrimaryColor != nil {
|
||||
wm.PrimaryColor = *e.PrimaryColor
|
||||
}
|
||||
if e.SecondaryColor != nil {
|
||||
wm.SecondaryColor = *e.SecondaryColor
|
||||
}
|
||||
case *policy.LabelPolicyRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type SecondFactorWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
MFAType domain.SecondFactorType
|
||||
State domain.FactorState
|
||||
}
|
||||
|
||||
func (wm *SecondFactorWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.SecondFactorAddedEvent:
|
||||
wm.MFAType = e.MFAType
|
||||
wm.State = domain.FactorStateActive
|
||||
case *policy.SecondFactorRemovedEvent:
|
||||
wm.MFAType = e.MFAType
|
||||
wm.State = domain.FactorStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
type MultiFactoryWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
MFAType domain.MultiFactorType
|
||||
State domain.FactorState
|
||||
}
|
||||
|
||||
func (wm *MultiFactoryWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.MultiFactorAddedEvent:
|
||||
wm.MFAType = e.MFAType
|
||||
wm.State = domain.FactorStateActive
|
||||
case *policy.MultiFactorRemovedEvent:
|
||||
wm.MFAType = e.MFAType
|
||||
wm.State = domain.FactorStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type LoginPolicyWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
AllowUserNamePassword bool
|
||||
AllowRegister bool
|
||||
AllowExternalIDP bool
|
||||
ForceMFA bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.LoginPolicyAddedEvent:
|
||||
wm.AllowRegister = e.AllowRegister
|
||||
wm.AllowUserNamePassword = e.AllowUserNamePassword
|
||||
wm.AllowExternalIDP = e.AllowExternalIDP
|
||||
wm.ForceMFA = e.ForceMFA
|
||||
wm.PasswordlessType = e.PasswordlessType
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.LoginPolicyChangedEvent:
|
||||
if e.AllowRegister != nil {
|
||||
wm.AllowRegister = *e.AllowRegister
|
||||
}
|
||||
if e.AllowUserNamePassword != nil {
|
||||
wm.AllowUserNamePassword = *e.AllowUserNamePassword
|
||||
}
|
||||
if e.AllowExternalIDP != nil {
|
||||
wm.AllowExternalIDP = *e.AllowExternalIDP
|
||||
}
|
||||
if e.ForceMFA != nil {
|
||||
wm.ForceMFA = *e.ForceMFA
|
||||
}
|
||||
if e.PasswordlessType != nil {
|
||||
wm.PasswordlessType = *e.PasswordlessType
|
||||
}
|
||||
case *policy.LoginPolicyRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type MailTemplateWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Template []byte
|
||||
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *MailTemplateWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.MailTemplateAddedEvent:
|
||||
wm.Template = e.Template
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.MailTemplateChangedEvent:
|
||||
if e.Template != nil {
|
||||
wm.Template = *e.Template
|
||||
}
|
||||
case *policy.MailTemplateRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type MailTextWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
MailTextType string
|
||||
Language string
|
||||
Title string
|
||||
PreHeader string
|
||||
Subject string
|
||||
Greeting string
|
||||
Text string
|
||||
ButtonText string
|
||||
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *MailTextWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.MailTextAddedEvent:
|
||||
if wm.MailTextType != e.MailTextType || wm.Language != e.Language {
|
||||
continue
|
||||
}
|
||||
wm.Title = e.Title
|
||||
wm.PreHeader = e.PreHeader
|
||||
wm.Subject = e.Subject
|
||||
wm.Greeting = e.Greeting
|
||||
wm.Text = e.Text
|
||||
wm.ButtonText = e.ButtonText
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.MailTextChangedEvent:
|
||||
if wm.MailTextType != e.MailTextType || wm.Language != e.Language {
|
||||
continue
|
||||
}
|
||||
if e.Title != nil {
|
||||
wm.Title = *e.Title
|
||||
}
|
||||
if e.PreHeader != nil {
|
||||
wm.PreHeader = *e.PreHeader
|
||||
}
|
||||
if e.Subject != nil {
|
||||
wm.Subject = *e.Subject
|
||||
}
|
||||
if e.Greeting != nil {
|
||||
wm.Greeting = *e.Greeting
|
||||
}
|
||||
if e.Text != nil {
|
||||
wm.Text = *e.Text
|
||||
}
|
||||
if e.ButtonText != nil {
|
||||
wm.ButtonText = *e.ButtonText
|
||||
}
|
||||
case *policy.MailTextRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type PolicyOrgIAMWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
UserLoginMustBeDomain bool
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *PolicyOrgIAMWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.OrgIAMPolicyAddedEvent:
|
||||
wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.OrgIAMPolicyChangedEvent:
|
||||
if e.UserLoginMustBeDomain != nil {
|
||||
wm.UserLoginMustBeDomain = *e.UserLoginMustBeDomain
|
||||
}
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type PasswordAgePolicyWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
ExpireWarnDays uint64
|
||||
MaxAgeDays uint64
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *PasswordAgePolicyWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.PasswordAgePolicyAddedEvent:
|
||||
wm.ExpireWarnDays = e.ExpireWarnDays
|
||||
wm.MaxAgeDays = e.MaxAgeDays
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.PasswordAgePolicyChangedEvent:
|
||||
if e.ExpireWarnDays != nil {
|
||||
wm.ExpireWarnDays = *e.ExpireWarnDays
|
||||
}
|
||||
if e.MaxAgeDays != nil {
|
||||
wm.MaxAgeDays = *e.MaxAgeDays
|
||||
}
|
||||
case *policy.PasswordAgePolicyRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type PasswordComplexityPolicyWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
MinLength uint64
|
||||
HasLowercase bool
|
||||
HasUppercase bool
|
||||
HasNumber bool
|
||||
HasSymbol bool
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *PasswordComplexityPolicyWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.PasswordComplexityPolicyAddedEvent:
|
||||
wm.MinLength = e.MinLength
|
||||
wm.HasLowercase = e.HasLowercase
|
||||
wm.HasUppercase = e.HasUppercase
|
||||
wm.HasNumber = e.HasNumber
|
||||
wm.HasSymbol = e.HasSymbol
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.PasswordComplexityPolicyChangedEvent:
|
||||
if e.MinLength != nil {
|
||||
wm.MinLength = *e.MinLength
|
||||
}
|
||||
if e.HasLowercase != nil {
|
||||
wm.HasLowercase = *e.HasLowercase
|
||||
}
|
||||
if e.HasUppercase != nil {
|
||||
wm.HasUppercase = *e.HasUppercase
|
||||
}
|
||||
if e.HasNumber != nil {
|
||||
wm.HasNumber = *e.HasNumber
|
||||
}
|
||||
if e.HasSymbol != nil {
|
||||
wm.HasSymbol = *e.HasSymbol
|
||||
}
|
||||
case *policy.PasswordComplexityPolicyRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||
)
|
||||
|
||||
type PasswordLockoutPolicyWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
MaxAttempts uint64
|
||||
ShowLockOutFailures bool
|
||||
State domain.PolicyState
|
||||
}
|
||||
|
||||
func (wm *PasswordLockoutPolicyWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *policy.PasswordLockoutPolicyAddedEvent:
|
||||
wm.MaxAttempts = e.MaxAttempts
|
||||
wm.ShowLockOutFailures = e.ShowLockOutFailures
|
||||
wm.State = domain.PolicyStateActive
|
||||
case *policy.PasswordLockoutPolicyChangedEvent:
|
||||
if e.MaxAttempts != nil {
|
||||
wm.MaxAttempts = *e.MaxAttempts
|
||||
}
|
||||
if e.ShowLockOutFailures != nil {
|
||||
wm.ShowLockOutFailures = *e.ShowLockOutFailures
|
||||
}
|
||||
case *policy.PasswordLockoutPolicyRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
@@ -1,187 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddProject(ctx context.Context, project *domain.Project, resourceOwner, ownerUserID string) (_ *domain.Project, err error) {
|
||||
events, addedProject, err := r.addProject(ctx, project, resourceOwner, ownerUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedProject, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectWriteModelToProject(addedProject), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addProject(ctx context.Context, projectAdd *domain.Project, resourceOwner, ownerUserID string) (_ []eventstore.EventPusher, _ *ProjectWriteModel, err error) {
|
||||
if !projectAdd.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-IOVCC", "Errors.Project.Invalid")
|
||||
}
|
||||
projectAdd.AggregateID, err = r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
addedProject := NewProjectWriteModel(projectAdd.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedProject.WriteModel)
|
||||
|
||||
projectRole := domain.RoleProjectOwner
|
||||
iam, err := r.GetIAM(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if iam.GlobalOrgID == resourceOwner {
|
||||
projectRole = domain.RoleProjectOwnerGlobal
|
||||
}
|
||||
events := []eventstore.EventPusher{
|
||||
project.NewProjectAddedEvent(ctx, projectAgg, projectAdd.Name),
|
||||
project.NewProjectMemberAddedEvent(ctx, projectAgg, ownerUserID, projectRole),
|
||||
}
|
||||
return events, addedProject, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getProjectByID(ctx context.Context, projectID, resourceOwner string) (*domain.Project, error) {
|
||||
projectWriteModel, err := r.getProjectWriteModelByID(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if projectWriteModel.State == domain.ProjectStateUnspecified || projectWriteModel.State == domain.ProjectStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "PROJECT-Gd2hh", "Errors.Project.NotFound")
|
||||
}
|
||||
return projectWriteModelToProject(projectWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) checkProjectExists(ctx context.Context, projectID, resourceOwner string) error {
|
||||
projectWriteModel, err := r.getProjectWriteModelByID(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if projectWriteModel.State == domain.ProjectStateUnspecified || projectWriteModel.State == domain.ProjectStateRemoved {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0fs", "Errors.Project.NotFound")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeProject(ctx context.Context, projectChange *domain.Project, resourceOwner string) (*domain.Project, error) {
|
||||
if !projectChange.IsValid() && projectChange.AggregateID != "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4m9vS", "Errors.Project.Invalid")
|
||||
}
|
||||
|
||||
existingProject, err := r.getProjectWriteModelByID(ctx, projectChange.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingProject.State == domain.ProjectStateUnspecified || existingProject.State == domain.ProjectStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.Project.NotFound")
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingProject.WriteModel)
|
||||
changedEvent, hasChanged, err := existingProject.NewChangedEvent(ctx, projectAgg, projectChange.Name, projectChange.ProjectRoleAssertion, projectChange.ProjectRoleCheck)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M0fs", "Errors.NoChangesFound")
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingProject, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectWriteModelToProject(existingProject), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) DeactivateProject(ctx context.Context, projectID string, resourceOwner string) error {
|
||||
if projectID == "" || resourceOwner == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-88iF0", "Errors.Project.ProjectIDMissing")
|
||||
}
|
||||
|
||||
existingProject, err := r.getProjectWriteModelByID(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingProject.State == domain.ProjectStateUnspecified || existingProject.State == domain.ProjectStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-112M9", "Errors.Project.NotFound")
|
||||
}
|
||||
if existingProject.State != domain.ProjectStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-mki55", "Errors.Project.NotActive")
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingProject.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewProjectDeactivatedEvent(ctx, projectAgg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) ReactivateProject(ctx context.Context, projectID string, resourceOwner string) error {
|
||||
if projectID == "" || resourceOwner == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4m9vS", "Errors.Project.ProjectIDMissing")
|
||||
}
|
||||
|
||||
existingProject, err := r.getProjectWriteModelByID(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingProject.State == domain.ProjectStateUnspecified || existingProject.State == domain.ProjectStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.Project.NotFound")
|
||||
}
|
||||
if existingProject.State != domain.ProjectStateInactive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5M9bs", "Errors.Project.NotInctive")
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingProject.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewProjectReactivatedEvent(ctx, projectAgg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveProject(ctx context.Context, projectID, resourceOwner string, cascadingUserGrantIDs ...string) error {
|
||||
if projectID == "" || resourceOwner == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-66hM9", "Errors.Project.ProjectIDMissing")
|
||||
}
|
||||
|
||||
existingProject, err := r.getProjectWriteModelByID(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingProject.State == domain.ProjectStateUnspecified || existingProject.State == domain.ProjectStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.Project.NotFound")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingProject.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
project.NewProjectRemovedEvent(ctx, projectAgg, existingProject.Name),
|
||||
}
|
||||
|
||||
for _, grantID := range cascadingUserGrantIDs {
|
||||
event, err := r.removeUserGrant(ctx, grantID, "", true)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-b8Djf", "usergrantid", grantID).WithError(err).Warn("could not cascade remove user grant")
|
||||
continue
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) getProjectWriteModelByID(ctx context.Context, projectID, resourceOwner string) (*ProjectWriteModel, error) {
|
||||
projectWriteModel := NewProjectWriteModel(projectID, resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, projectWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectWriteModel, nil
|
||||
}
|
@@ -1,105 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) ChangeApplication(ctx context.Context, projectID string, appChange domain.Application, resourceOwner string) (domain.Application, error) {
|
||||
if appChange.GetAppID() == "" || appChange.GetApplicationName() == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4m9vS", "Errors.Project.App.Invalid")
|
||||
}
|
||||
|
||||
existingApp, err := r.getApplicationWriteModel(ctx, projectID, appChange.GetAppID(), resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingApp.State == domain.AppStateUnspecified || existingApp.State == domain.AppStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-28di9", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
if existingApp.Name == appChange.GetApplicationName() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2m8vx", "Errors.NoChangesFound")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingApp.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(
|
||||
ctx,
|
||||
project.NewApplicationChangedEvent(ctx, projectAgg, appChange.GetAppID(), existingApp.Name, appChange.GetApplicationName(), projectID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingApp, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return applicationWriteModelToApplication(existingApp), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) DeactivateApplication(ctx context.Context, projectID, appID, resourceOwner string) error {
|
||||
if projectID == "" || appID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-88fi0", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
existingApp, err := r.getApplicationWriteModel(ctx, projectID, appID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingApp.State == domain.AppStateUnspecified || existingApp.State == domain.AppStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-ov9d3", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
if existingApp.State != domain.AppStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-dsh35", "Errors.Project.App.NotActive")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingApp.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewApplicationDeactivatedEvent(ctx, projectAgg, appID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) ReactivateApplication(ctx context.Context, projectID, appID, resourceOwner string) error {
|
||||
if projectID == "" || appID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-983dF", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
existingApp, err := r.getApplicationWriteModel(ctx, projectID, appID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingApp.State == domain.AppStateUnspecified || existingApp.State == domain.AppStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-ov9d3", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
if existingApp.State != domain.AppStateInactive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-1n8cM", "Errors.Project.App.NotInactive")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingApp.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewApplicationReactivatedEvent(ctx, projectAgg, appID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveApplication(ctx context.Context, projectID, appID, resourceOwner string) error {
|
||||
if projectID == "" || appID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-1b7Jf", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
existingApp, err := r.getApplicationWriteModel(ctx, projectID, appID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingApp.State == domain.AppStateUnspecified || existingApp.State == domain.AppStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-0po9s", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingApp.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewApplicationRemovedEvent(ctx, projectAgg, appID, existingApp.Name, projectID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) getApplicationWriteModel(ctx context.Context, projectID, appID, resourceOwner string) (*ApplicationWriteModel, error) {
|
||||
appWriteModel := NewApplicationWriteModelWithAppIDC(projectID, appID, resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, appWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appWriteModel, nil
|
||||
}
|
@@ -1,145 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddAPIApplication(ctx context.Context, application *domain.APIApp, resourceOwner string) (_ *domain.APIApp, err error) {
|
||||
project, err := r.getProjectByID(ctx, application.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedApplication := NewAPIApplicationWriteModel(application.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedApplication.WriteModel)
|
||||
events, stringPw, err := r.addAPIApplication(ctx, projectAgg, project, application, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedApplication.AppID = application.AppID
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedApplication, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := apiWriteModelToAPIConfig(addedApplication)
|
||||
result.ClientSecretString = stringPw
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addAPIApplication(ctx context.Context, projectAgg *eventstore.Aggregate, proj *domain.Project, apiAppApp *domain.APIApp, resourceOwner string) (events []eventstore.EventPusher, stringPW string, err error) {
|
||||
if !apiAppApp.IsValid() {
|
||||
return nil, "", caos_errs.ThrowPreconditionFailed(nil, "PROJECT-Bff2g", "Errors.Application.Invalid")
|
||||
}
|
||||
apiAppApp.AppID, err = r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
events = []eventstore.EventPusher{
|
||||
project.NewApplicationAddedEvent(ctx, projectAgg, apiAppApp.AppID, apiAppApp.AppName, resourceOwner),
|
||||
}
|
||||
|
||||
var stringPw string
|
||||
err = domain.SetNewClientID(apiAppApp, r.idGenerator, proj)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
stringPw, err = domain.SetNewClientSecretIfNeeded(apiAppApp, r.applicationSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
events = append(events, project.NewAPIConfigAddedEvent(ctx,
|
||||
projectAgg,
|
||||
apiAppApp.AppID,
|
||||
apiAppApp.ClientID,
|
||||
apiAppApp.ClientSecret,
|
||||
apiAppApp.AuthMethodType))
|
||||
|
||||
return events, stringPw, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeAPIApplication(ctx context.Context, apiApp *domain.APIApp, resourceOwner string) (*domain.APIApp, error) {
|
||||
if !apiApp.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-1m900", "Errors.Project.App.APIConfigInvalid")
|
||||
}
|
||||
|
||||
existingAPI, err := r.getAPIAppWriteModel(ctx, apiApp.AggregateID, apiApp.AppID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingAPI.State == domain.AppStateUnspecified || existingAPI.State == domain.AppStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-2n8uU", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingAPI.WriteModel)
|
||||
changedEvent, hasChanged, err := existingAPI.NewChangedEvent(
|
||||
ctx,
|
||||
projectAgg,
|
||||
apiApp.AppID,
|
||||
apiApp.AuthMethodType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-1m88i", "Errors.NoChangesFound")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingAPI, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := apiWriteModelToAPIConfig(existingAPI)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeAPIApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string) (*domain.APIApp, error) {
|
||||
if projectID == "" || appID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-99i83", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
existingAPI, err := r.getAPIAppWriteModel(ctx, projectID, appID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingAPI.State == domain.AppStateUnspecified || existingAPI.State == domain.AppStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-2g66f", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
cryptoSecret, stringPW, err := domain.NewClientSecret(r.applicationSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingAPI.WriteModel)
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, project.NewAPIConfigSecretChangedEvent(ctx, projectAgg, appID, cryptoSecret))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingAPI, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := apiWriteModelToAPIConfig(existingAPI)
|
||||
result.ClientSecretString = stringPW
|
||||
return result, err
|
||||
}
|
||||
func (r *CommandSide) getAPIAppWriteModel(ctx context.Context, projectID, appID, resourceOwner string) (*APIApplicationWriteModel, error) {
|
||||
appWriteModel := NewAPIApplicationWriteModelWithAppID(projectID, appID, resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, appWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appWriteModel, nil
|
||||
}
|
@@ -1,173 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type APIApplicationWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
AppID string
|
||||
AppName string
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
ClientSecretString string
|
||||
AuthMethodType domain.APIAuthMethodType
|
||||
State domain.AppState
|
||||
}
|
||||
|
||||
func NewAPIApplicationWriteModelWithAppID(projectID, appID, resourceOwner string) *APIApplicationWriteModel {
|
||||
return &APIApplicationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
AppID: appID,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAPIApplicationWriteModel(projectID, resourceOwner string) *APIApplicationWriteModel {
|
||||
return &APIApplicationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
func (wm *APIApplicationWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationAddedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationDeactivatedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationReactivatedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationRemovedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.APIConfigAddedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.APIConfigChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.APIConfigSecretChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *APIApplicationWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationAddedEvent:
|
||||
wm.AppName = e.Name
|
||||
wm.State = domain.AppStateActive
|
||||
case *project.ApplicationChangedEvent:
|
||||
wm.AppName = e.Name
|
||||
case *project.ApplicationDeactivatedEvent:
|
||||
if wm.State == domain.AppStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.AppStateInactive
|
||||
case *project.ApplicationReactivatedEvent:
|
||||
if wm.State == domain.AppStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.AppStateActive
|
||||
case *project.ApplicationRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
case *project.APIConfigAddedEvent:
|
||||
wm.appendAddAPIEvent(e)
|
||||
case *project.APIConfigChangedEvent:
|
||||
wm.appendChangeAPIEvent(e)
|
||||
case *project.APIConfigSecretChangedEvent:
|
||||
wm.ClientSecret = e.ClientSecret
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *APIApplicationWriteModel) appendAddAPIEvent(e *project.APIConfigAddedEvent) {
|
||||
wm.ClientID = e.ClientID
|
||||
wm.ClientSecret = e.ClientSecret
|
||||
wm.AuthMethodType = e.AuthMethodType
|
||||
}
|
||||
|
||||
func (wm *APIApplicationWriteModel) appendChangeAPIEvent(e *project.APIConfigChangedEvent) {
|
||||
if e.AuthMethodType != nil {
|
||||
wm.AuthMethodType = *e.AuthMethodType
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *APIApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
project.ApplicationAddedType,
|
||||
project.ApplicationChangedType,
|
||||
project.ApplicationDeactivatedType,
|
||||
project.ApplicationReactivatedType,
|
||||
project.ApplicationRemovedType,
|
||||
project.APIConfigAddedType,
|
||||
project.APIConfigChangedType,
|
||||
project.APIConfigSecretChangedType,
|
||||
project.ProjectRemovedType,
|
||||
)
|
||||
}
|
||||
|
||||
func (wm *APIApplicationWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
appID string,
|
||||
authMethodType domain.APIAuthMethodType,
|
||||
) (*project.APIConfigChangedEvent, bool, error) {
|
||||
changes := make([]project.APIConfigChanges, 0)
|
||||
var err error
|
||||
|
||||
if wm.AuthMethodType != authMethodType {
|
||||
changes = append(changes, project.ChangeAPIAuthMethodType(authMethodType))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := project.NewAPIConfigChangedEvent(ctx, aggregate, appID, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddApplicationKey(ctx context.Context, key *domain.ApplicationKey, resourceOwner string) (_ *domain.ApplicationKey, err error) {
|
||||
application, err := r.getApplicationWriteModel(ctx, key.AggregateID, key.ApplicationID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !application.State.Exists() {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "COMMAND-sak25", "Errors.Application.NotFound")
|
||||
}
|
||||
key.KeyID, err = r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyWriteModel := NewApplicationKeyWriteModel(key.AggregateID, key.ApplicationID, key.KeyID, resourceOwner)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, keyWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !keyWriteModel.KeysAllowed {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "COMMAND-Dff54", "Errors.Project.App.AuthMethodNoPrivateKeyJWT")
|
||||
}
|
||||
|
||||
if err := domain.EnsureValidExpirationDate(key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = domain.SetNewAuthNKeyPair(key, r.applicationKeySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key.ClientID = keyWriteModel.ClientID
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx,
|
||||
project.NewApplicationKeyAddedEvent(
|
||||
ctx,
|
||||
ProjectAggregateFromWriteModel(&keyWriteModel.WriteModel),
|
||||
key.ApplicationID,
|
||||
key.ClientID,
|
||||
key.KeyID,
|
||||
key.Type,
|
||||
key.ExpirationDate,
|
||||
key.PublicKey),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(keyWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := applicationKeyWriteModelToKey(keyWriteModel, key.PrivateKey)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveApplicationKey(ctx context.Context, projectID, applicationID, keyID, resourceOwner string) error {
|
||||
keyWriteModel := NewApplicationKeyWriteModel(projectID, applicationID, keyID, resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, keyWriteModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !keyWriteModel.State.Exists() {
|
||||
return errors.ThrowNotFound(nil, "COMMAND-4m77G", "Errors.Application.Key.NotFound")
|
||||
}
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewApplicationKeyRemovedEvent(ctx, ProjectAggregateFromWriteModel(&keyWriteModel.WriteModel), keyID))
|
||||
return err
|
||||
}
|
@@ -1,141 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type ApplicationKeyWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
AppID string
|
||||
ClientID string
|
||||
KeyID string
|
||||
KeyType domain.AuthNKeyType
|
||||
ExpirationDate time.Time
|
||||
|
||||
State domain.AppState
|
||||
KeysAllowed bool
|
||||
}
|
||||
|
||||
func NewApplicationKeyWriteModel(projectID, appID, keyID, resourceOwner string) *ApplicationKeyWriteModel {
|
||||
return &ApplicationKeyWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
AppID: appID,
|
||||
KeyID: keyID,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ApplicationKeyWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationRemovedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.OIDCConfigAddedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.OIDCConfigChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.APIConfigAddedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.APIConfigChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationKeyAddedEvent:
|
||||
if e.AppID != wm.AppID || e.KeyID != wm.KeyID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationKeyRemovedEvent:
|
||||
if e.KeyID != wm.KeyID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ApplicationKeyWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
case *project.OIDCConfigAddedEvent:
|
||||
wm.appendAddOIDCEvent(e)
|
||||
case *project.OIDCConfigChangedEvent:
|
||||
wm.appendChangeOIDCEvent(e)
|
||||
case *project.APIConfigAddedEvent:
|
||||
wm.appendAddAPIEvent(e)
|
||||
case *project.APIConfigChangedEvent:
|
||||
wm.appendChangeAPIEvent(e)
|
||||
case *project.ApplicationKeyAddedEvent:
|
||||
wm.ClientID = e.ClientID
|
||||
wm.ExpirationDate = e.ExpirationDate
|
||||
wm.KeyType = e.KeyType
|
||||
case *project.ApplicationKeyRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ApplicationKeyWriteModel) appendAddOIDCEvent(e *project.OIDCConfigAddedEvent) {
|
||||
wm.ClientID = e.ClientID
|
||||
wm.KeysAllowed = e.AuthMethodType == domain.OIDCAuthMethodTypePrivateKeyJWT
|
||||
}
|
||||
|
||||
func (wm *ApplicationKeyWriteModel) appendChangeOIDCEvent(e *project.OIDCConfigChangedEvent) {
|
||||
if e.AuthMethodType != nil {
|
||||
wm.KeysAllowed = *e.AuthMethodType == domain.OIDCAuthMethodTypePrivateKeyJWT
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ApplicationKeyWriteModel) appendAddAPIEvent(e *project.APIConfigAddedEvent) {
|
||||
wm.ClientID = e.ClientID
|
||||
wm.KeysAllowed = e.AuthMethodType == domain.APIAuthMethodTypePrivateKeyJWT
|
||||
}
|
||||
|
||||
func (wm *ApplicationKeyWriteModel) appendChangeAPIEvent(e *project.APIConfigChangedEvent) {
|
||||
if e.AuthMethodType != nil {
|
||||
wm.KeysAllowed = *e.AuthMethodType == domain.APIAuthMethodTypePrivateKeyJWT
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ApplicationKeyWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
project.ApplicationRemovedType,
|
||||
project.OIDCConfigAddedType,
|
||||
project.OIDCConfigChangedType,
|
||||
project.APIConfigAddedType,
|
||||
project.APIConfigChangedType,
|
||||
project.ApplicationKeyAddedEventType,
|
||||
project.ApplicationKeyRemovedEventType,
|
||||
project.ProjectRemovedType,
|
||||
)
|
||||
}
|
@@ -1,108 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type ApplicationWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
AppID string
|
||||
State domain.AppState
|
||||
Name string
|
||||
}
|
||||
|
||||
func NewApplicationWriteModelWithAppIDC(projectID, appID, resourceOwner string) *ApplicationWriteModel {
|
||||
return &ApplicationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
AppID: appID,
|
||||
}
|
||||
}
|
||||
|
||||
func NewApplicationWriteModel(projectID, resourceOwner string) *ApplicationWriteModel {
|
||||
return &ApplicationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
func (wm *ApplicationWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationAddedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationDeactivatedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationReactivatedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationRemovedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ApplicationWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationAddedEvent:
|
||||
wm.Name = e.Name
|
||||
wm.State = domain.AppStateActive
|
||||
case *project.ApplicationChangedEvent:
|
||||
wm.Name = e.Name
|
||||
case *project.ApplicationDeactivatedEvent:
|
||||
if wm.State == domain.AppStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.AppStateInactive
|
||||
case *project.ApplicationReactivatedEvent:
|
||||
if wm.State == domain.AppStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.AppStateActive
|
||||
case *project.ApplicationRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
project.ApplicationAddedType,
|
||||
project.ApplicationChangedType,
|
||||
project.ApplicationDeactivatedType,
|
||||
project.ApplicationReactivatedType,
|
||||
project.ApplicationRemovedType,
|
||||
project.ProjectRemovedType,
|
||||
)
|
||||
}
|
@@ -1,202 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddOIDCApplication(ctx context.Context, application *domain.OIDCApp, resourceOwner string) (_ *domain.OIDCApp, err error) {
|
||||
project, err := r.getProjectByID(ctx, application.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedApplication := NewOIDCApplicationWriteModel(application.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedApplication.WriteModel)
|
||||
events, stringPw, err := r.addOIDCApplication(ctx, projectAgg, project, application, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedApplication.AppID = application.AppID
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedApplication, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := oidcWriteModelToOIDCConfig(addedApplication)
|
||||
result.ClientSecretString = stringPw
|
||||
result.FillCompliance()
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOIDCApplication(ctx context.Context, projectAgg *eventstore.Aggregate, proj *domain.Project, oidcApp *domain.OIDCApp, resourceOwner string) (events []eventstore.EventPusher, stringPW string, err error) {
|
||||
if !oidcApp.IsValid() {
|
||||
return nil, "", caos_errs.ThrowPreconditionFailed(nil, "PROJECT-Bff2g", "Errors.Application.Invalid")
|
||||
}
|
||||
oidcApp.AppID, err = r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
events = []eventstore.EventPusher{
|
||||
project.NewApplicationAddedEvent(ctx, projectAgg, oidcApp.AppID, oidcApp.AppName, resourceOwner),
|
||||
}
|
||||
|
||||
var stringPw string
|
||||
err = domain.SetNewClientID(oidcApp, r.idGenerator, proj)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
stringPw, err = domain.SetNewClientSecretIfNeeded(oidcApp, r.applicationSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
events = append(events, project.NewOIDCConfigAddedEvent(ctx,
|
||||
projectAgg,
|
||||
oidcApp.OIDCVersion,
|
||||
oidcApp.AppID,
|
||||
oidcApp.ClientID,
|
||||
oidcApp.ClientSecret,
|
||||
oidcApp.RedirectUris,
|
||||
oidcApp.ResponseTypes,
|
||||
oidcApp.GrantTypes,
|
||||
oidcApp.ApplicationType,
|
||||
oidcApp.AuthMethodType,
|
||||
oidcApp.PostLogoutRedirectUris,
|
||||
oidcApp.DevMode,
|
||||
oidcApp.AccessTokenType,
|
||||
oidcApp.AccessTokenRoleAssertion,
|
||||
oidcApp.IDTokenRoleAssertion,
|
||||
oidcApp.IDTokenUserinfoAssertion,
|
||||
oidcApp.ClockSkew))
|
||||
|
||||
return events, stringPw, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeOIDCApplication(ctx context.Context, oidc *domain.OIDCApp, resourceOwner string) (*domain.OIDCApp, error) {
|
||||
if !oidc.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-1m900", "Errors.Project.App.OIDCConfigInvalid")
|
||||
}
|
||||
|
||||
existingOIDC, err := r.getOIDCAppWriteModel(ctx, oidc.AggregateID, oidc.AppID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingOIDC.State == domain.AppStateUnspecified || existingOIDC.State == domain.AppStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-2n8uU", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingOIDC.WriteModel)
|
||||
changedEvent, hasChanged, err := existingOIDC.NewChangedEvent(
|
||||
ctx,
|
||||
projectAgg,
|
||||
oidc.AppID,
|
||||
oidc.RedirectUris,
|
||||
oidc.PostLogoutRedirectUris,
|
||||
oidc.ResponseTypes,
|
||||
oidc.GrantTypes,
|
||||
oidc.ApplicationType,
|
||||
oidc.AuthMethodType,
|
||||
oidc.OIDCVersion,
|
||||
oidc.AccessTokenType,
|
||||
oidc.DevMode,
|
||||
oidc.AccessTokenRoleAssertion,
|
||||
oidc.IDTokenRoleAssertion,
|
||||
oidc.IDTokenUserinfoAssertion,
|
||||
oidc.ClockSkew)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-1m88i", "Errors.NoChangesFound")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingOIDC, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := oidcWriteModelToOIDCConfig(existingOIDC)
|
||||
result.FillCompliance()
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeOIDCApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string) (*domain.OIDCApp, error) {
|
||||
if projectID == "" || appID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-99i83", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
existingOIDC, err := r.getOIDCAppWriteModel(ctx, projectID, appID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingOIDC.State == domain.AppStateUnspecified || existingOIDC.State == domain.AppStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-2g66f", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
cryptoSecret, stringPW, err := domain.NewClientSecret(r.applicationSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingOIDC.WriteModel)
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, project.NewOIDCConfigSecretChangedEvent(ctx, projectAgg, appID, cryptoSecret))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingOIDC, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := oidcWriteModelToOIDCConfig(existingOIDC)
|
||||
result.ClientSecretString = stringPW
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (r *CommandSide) VerifyOIDCClientSecret(ctx context.Context, projectID, appID, secret string) error {
|
||||
app, err := r.getOIDCAppWriteModel(ctx, projectID, appID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !app.State.Exists() {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-D6hba", "Errors.Project.App.NoExisting")
|
||||
}
|
||||
if app.ClientSecret == nil {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-D6hba", "Errors.Project.App.OIDCConfigInvalid")
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&app.WriteModel)
|
||||
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "crypto.CompareHash")
|
||||
err = crypto.CompareHash(app.ClientSecret, []byte(secret), r.userPasswordAlg)
|
||||
spanPasswordComparison.EndWithError(err)
|
||||
if err == nil {
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewOIDCConfigSecretCheckSucceededEvent(ctx, projectAgg, app.AppID))
|
||||
return err
|
||||
}
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewOIDCConfigSecretCheckFailedEvent(ctx, projectAgg, app.AppID))
|
||||
logging.Log("COMMAND-ADfhz").OnError(err).Error("could not push event OIDCClientSecretCheckFailed")
|
||||
return caos_errs.ThrowInvalidArgument(nil, "COMMAND-Bz542", "Errors.Project.App.OIDCSecretInvalid")
|
||||
}
|
||||
|
||||
func (r *CommandSide) getOIDCAppWriteModel(ctx context.Context, projectID, appID, resourceOwner string) (*OIDCApplicationWriteModel, error) {
|
||||
appWriteModel := NewOIDCApplicationWriteModelWithAppID(projectID, appID, resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, appWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appWriteModel, nil
|
||||
}
|
@@ -1,283 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
type OIDCApplicationWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
AppID string
|
||||
AppName string
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
ClientSecretString string
|
||||
RedirectUris []string
|
||||
ResponseTypes []domain.OIDCResponseType
|
||||
GrantTypes []domain.OIDCGrantType
|
||||
ApplicationType domain.OIDCApplicationType
|
||||
AuthMethodType domain.OIDCAuthMethodType
|
||||
PostLogoutRedirectUris []string
|
||||
OIDCVersion domain.OIDCVersion
|
||||
Compliance *domain.Compliance
|
||||
DevMode bool
|
||||
AccessTokenType domain.OIDCTokenType
|
||||
AccessTokenRoleAssertion bool
|
||||
IDTokenRoleAssertion bool
|
||||
IDTokenUserinfoAssertion bool
|
||||
ClockSkew time.Duration
|
||||
State domain.AppState
|
||||
}
|
||||
|
||||
func NewOIDCApplicationWriteModelWithAppID(projectID, appID, resourceOwner string) *OIDCApplicationWriteModel {
|
||||
return &OIDCApplicationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
AppID: appID,
|
||||
}
|
||||
}
|
||||
|
||||
func NewOIDCApplicationWriteModel(projectID, resourceOwner string) *OIDCApplicationWriteModel {
|
||||
return &OIDCApplicationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
func (wm *OIDCApplicationWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationAddedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationDeactivatedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationReactivatedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ApplicationRemovedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.OIDCConfigAddedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.OIDCConfigChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.OIDCConfigSecretChangedEvent:
|
||||
if e.AppID != wm.AppID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OIDCApplicationWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationAddedEvent:
|
||||
wm.AppName = e.Name
|
||||
wm.State = domain.AppStateActive
|
||||
case *project.ApplicationChangedEvent:
|
||||
wm.AppName = e.Name
|
||||
case *project.ApplicationDeactivatedEvent:
|
||||
if wm.State == domain.AppStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.AppStateInactive
|
||||
case *project.ApplicationReactivatedEvent:
|
||||
if wm.State == domain.AppStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.AppStateActive
|
||||
case *project.ApplicationRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
case *project.OIDCConfigAddedEvent:
|
||||
wm.appendAddOIDCEvent(e)
|
||||
case *project.OIDCConfigChangedEvent:
|
||||
wm.appendChangeOIDCEvent(e)
|
||||
case *project.OIDCConfigSecretChangedEvent:
|
||||
wm.ClientSecret = e.ClientSecret
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.State = domain.AppStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OIDCApplicationWriteModel) appendAddOIDCEvent(e *project.OIDCConfigAddedEvent) {
|
||||
wm.ClientID = e.ClientID
|
||||
wm.ClientSecret = e.ClientSecret
|
||||
wm.RedirectUris = e.RedirectUris
|
||||
wm.ResponseTypes = e.ResponseTypes
|
||||
wm.GrantTypes = e.GrantTypes
|
||||
wm.ApplicationType = e.ApplicationType
|
||||
wm.AuthMethodType = e.AuthMethodType
|
||||
wm.PostLogoutRedirectUris = e.PostLogoutRedirectUris
|
||||
wm.OIDCVersion = e.Version
|
||||
wm.DevMode = e.DevMode
|
||||
wm.AccessTokenType = e.AccessTokenType
|
||||
wm.AccessTokenRoleAssertion = e.AccessTokenRoleAssertion
|
||||
wm.IDTokenRoleAssertion = e.IDTokenRoleAssertion
|
||||
wm.IDTokenUserinfoAssertion = e.IDTokenUserinfoAssertion
|
||||
wm.ClockSkew = e.ClockSkew
|
||||
}
|
||||
|
||||
func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfigChangedEvent) {
|
||||
if e.RedirectUris != nil {
|
||||
wm.RedirectUris = *e.RedirectUris
|
||||
}
|
||||
if e.ResponseTypes != nil {
|
||||
wm.ResponseTypes = *e.ResponseTypes
|
||||
}
|
||||
if e.GrantTypes != nil {
|
||||
wm.GrantTypes = *e.GrantTypes
|
||||
}
|
||||
if e.ApplicationType != nil {
|
||||
wm.ApplicationType = *e.ApplicationType
|
||||
}
|
||||
if e.AuthMethodType != nil {
|
||||
wm.AuthMethodType = *e.AuthMethodType
|
||||
}
|
||||
if e.PostLogoutRedirectUris != nil {
|
||||
wm.PostLogoutRedirectUris = *e.PostLogoutRedirectUris
|
||||
}
|
||||
if e.Version != nil {
|
||||
wm.OIDCVersion = *e.Version
|
||||
}
|
||||
if e.DevMode != nil {
|
||||
wm.DevMode = *e.DevMode
|
||||
}
|
||||
if e.AccessTokenType != nil {
|
||||
wm.AccessTokenType = *e.AccessTokenType
|
||||
}
|
||||
if e.AccessTokenRoleAssertion != nil {
|
||||
wm.AccessTokenRoleAssertion = *e.AccessTokenRoleAssertion
|
||||
}
|
||||
if e.IDTokenRoleAssertion != nil {
|
||||
wm.IDTokenRoleAssertion = *e.IDTokenRoleAssertion
|
||||
}
|
||||
if e.IDTokenUserinfoAssertion != nil {
|
||||
wm.IDTokenUserinfoAssertion = *e.IDTokenUserinfoAssertion
|
||||
}
|
||||
if e.ClockSkew != nil {
|
||||
wm.ClockSkew = *e.ClockSkew
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OIDCApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
project.ApplicationAddedType,
|
||||
project.ApplicationChangedType,
|
||||
project.ApplicationDeactivatedType,
|
||||
project.ApplicationReactivatedType,
|
||||
project.ApplicationRemovedType,
|
||||
project.OIDCConfigAddedType,
|
||||
project.OIDCConfigChangedType,
|
||||
project.OIDCConfigSecretChangedType,
|
||||
project.ProjectRemovedType,
|
||||
)
|
||||
}
|
||||
|
||||
func (wm *OIDCApplicationWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
appID string,
|
||||
redirectURIS,
|
||||
postLogoutRedirectURIs []string,
|
||||
responseTypes []domain.OIDCResponseType,
|
||||
grantTypes []domain.OIDCGrantType,
|
||||
appType domain.OIDCApplicationType,
|
||||
authMethodType domain.OIDCAuthMethodType,
|
||||
oidcVersion domain.OIDCVersion,
|
||||
accessTokenType domain.OIDCTokenType,
|
||||
devMode,
|
||||
accessTokenRoleAssertion,
|
||||
idTokenRoleAssertion,
|
||||
idTokenUserinfoAssertion bool,
|
||||
clockSkew time.Duration,
|
||||
) (*project.OIDCConfigChangedEvent, bool, error) {
|
||||
changes := make([]project.OIDCConfigChanges, 0)
|
||||
var err error
|
||||
|
||||
if !reflect.DeepEqual(wm.RedirectUris, redirectURIS) {
|
||||
changes = append(changes, project.ChangeRedirectURIs(redirectURIS))
|
||||
}
|
||||
if !reflect.DeepEqual(wm.ResponseTypes, responseTypes) {
|
||||
changes = append(changes, project.ChangeResponseTypes(responseTypes))
|
||||
}
|
||||
if !reflect.DeepEqual(wm.GrantTypes, grantTypes) {
|
||||
changes = append(changes, project.ChangeGrantTypes(grantTypes))
|
||||
}
|
||||
if wm.ApplicationType != appType {
|
||||
changes = append(changes, project.ChangeApplicationType(appType))
|
||||
}
|
||||
if wm.AuthMethodType != authMethodType {
|
||||
changes = append(changes, project.ChangeAuthMethodType(authMethodType))
|
||||
}
|
||||
if !reflect.DeepEqual(wm.PostLogoutRedirectUris, postLogoutRedirectURIs) {
|
||||
changes = append(changes, project.ChangePostLogoutRedirectURIs(postLogoutRedirectURIs))
|
||||
}
|
||||
if wm.OIDCVersion != oidcVersion {
|
||||
changes = append(changes, project.ChangeVersion(oidcVersion))
|
||||
}
|
||||
if wm.DevMode != devMode {
|
||||
changes = append(changes, project.ChangeDevMode(devMode))
|
||||
}
|
||||
if wm.AccessTokenType != accessTokenType {
|
||||
changes = append(changes, project.ChangeAccessTokenType(accessTokenType))
|
||||
}
|
||||
if wm.AccessTokenRoleAssertion != accessTokenRoleAssertion {
|
||||
changes = append(changes, project.ChangeAccessTokenRoleAssertion(accessTokenRoleAssertion))
|
||||
}
|
||||
if wm.IDTokenRoleAssertion != idTokenRoleAssertion {
|
||||
changes = append(changes, project.ChangeIDTokenRoleAssertion(idTokenRoleAssertion))
|
||||
}
|
||||
if wm.IDTokenUserinfoAssertion != idTokenUserinfoAssertion {
|
||||
changes = append(changes, project.ChangeIDTokenUserinfoAssertion(idTokenUserinfoAssertion))
|
||||
}
|
||||
if wm.ClockSkew != clockSkew {
|
||||
changes = append(changes, project.ChangeClockSkew(clockSkew))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := project.NewOIDCConfigChangedEvent(ctx, aggregate, appID, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
func projectWriteModelToProject(writeModel *ProjectWriteModel) *domain.Project {
|
||||
return &domain.Project{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
Name: writeModel.Name,
|
||||
ProjectRoleAssertion: writeModel.ProjectRoleAssertion,
|
||||
ProjectRoleCheck: writeModel.ProjectRoleCheck,
|
||||
}
|
||||
}
|
||||
|
||||
func projectGrantWriteModelToProjectGrant(writeModel *ProjectGrantWriteModel) *domain.ProjectGrant {
|
||||
return &domain.ProjectGrant{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
GrantID: writeModel.GrantID,
|
||||
GrantedOrgID: writeModel.GrantedOrgID,
|
||||
RoleKeys: writeModel.RoleKeys,
|
||||
State: writeModel.State,
|
||||
}
|
||||
}
|
||||
|
||||
func applicationWriteModelToApplication(writeModel *ApplicationWriteModel) domain.Application {
|
||||
return &domain.ChangeApp{
|
||||
AppID: writeModel.AppID,
|
||||
AppName: writeModel.Name,
|
||||
State: writeModel.State,
|
||||
}
|
||||
}
|
||||
|
||||
func oidcWriteModelToOIDCConfig(writeModel *OIDCApplicationWriteModel) *domain.OIDCApp {
|
||||
return &domain.OIDCApp{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
AppID: writeModel.AppID,
|
||||
AppName: writeModel.AppName,
|
||||
State: writeModel.State,
|
||||
ClientID: writeModel.ClientID,
|
||||
ClientSecret: writeModel.ClientSecret,
|
||||
RedirectUris: writeModel.RedirectUris,
|
||||
ResponseTypes: writeModel.ResponseTypes,
|
||||
GrantTypes: writeModel.GrantTypes,
|
||||
ApplicationType: writeModel.ApplicationType,
|
||||
AuthMethodType: writeModel.AuthMethodType,
|
||||
PostLogoutRedirectUris: writeModel.PostLogoutRedirectUris,
|
||||
OIDCVersion: writeModel.OIDCVersion,
|
||||
DevMode: writeModel.DevMode,
|
||||
AccessTokenType: writeModel.AccessTokenType,
|
||||
AccessTokenRoleAssertion: writeModel.AccessTokenRoleAssertion,
|
||||
IDTokenRoleAssertion: writeModel.IDTokenRoleAssertion,
|
||||
IDTokenUserinfoAssertion: writeModel.IDTokenUserinfoAssertion,
|
||||
ClockSkew: writeModel.ClockSkew,
|
||||
}
|
||||
}
|
||||
|
||||
func apiWriteModelToAPIConfig(writeModel *APIApplicationWriteModel) *domain.APIApp {
|
||||
return &domain.APIApp{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
AppID: writeModel.AppID,
|
||||
AppName: writeModel.AppName,
|
||||
State: writeModel.State,
|
||||
ClientID: writeModel.ClientID,
|
||||
ClientSecret: writeModel.ClientSecret,
|
||||
AuthMethodType: writeModel.AuthMethodType,
|
||||
}
|
||||
}
|
||||
|
||||
func roleWriteModelToRole(writeModel *ProjectRoleWriteModel) *domain.ProjectRole {
|
||||
return &domain.ProjectRole{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
Key: writeModel.Key,
|
||||
DisplayName: writeModel.DisplayName,
|
||||
Group: writeModel.Group,
|
||||
}
|
||||
}
|
||||
|
||||
func memberWriteModelToProjectGrantMember(writeModel *ProjectGrantMemberWriteModel) *domain.ProjectGrantMember {
|
||||
return &domain.ProjectGrantMember{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
Roles: writeModel.Roles,
|
||||
GrantID: writeModel.GrantID,
|
||||
UserID: writeModel.UserID,
|
||||
}
|
||||
}
|
||||
|
||||
func applicationKeyWriteModelToKey(wm *ApplicationKeyWriteModel, privateKey []byte) *domain.ApplicationKey {
|
||||
return &domain.ApplicationKey{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
ApplicationID: wm.AppID,
|
||||
ClientID: wm.ClientID,
|
||||
KeyID: wm.KeyID,
|
||||
Type: wm.KeyType,
|
||||
ExpirationDate: wm.ExpirationDate,
|
||||
PrivateKey: privateKey,
|
||||
}
|
||||
}
|
@@ -1,212 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddProjectGrant(ctx context.Context, grant *domain.ProjectGrant, resourceOwner string) (_ *domain.ProjectGrant, err error) {
|
||||
if !grant.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-Bff2g", "Errors.Project.Grant.Invalid")
|
||||
}
|
||||
grant.GrantID, err = r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.checkProjectExists(ctx, grant.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.checkOrgExists(ctx, grant.GrantedOrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedGrant := NewProjectGrantWriteModel(grant.GrantID, grant.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedGrant.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(
|
||||
ctx,
|
||||
project.NewGrantAddedEvent(ctx, projectAgg, grant.GrantID, grant.GrantedOrgID, grant.AggregateID, grant.RoleKeys))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedGrant, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectGrantWriteModelToProjectGrant(addedGrant), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeProjectGrant(ctx context.Context, grant *domain.ProjectGrant, resourceOwner string, cascadeUserGrantIDs ...string) (_ *domain.ProjectGrant, err error) {
|
||||
if grant.GrantID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-1j83s", "Errors.IDMissing")
|
||||
}
|
||||
err = r.checkProjectExists(ctx, grant.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingGrant, err := r.projectGrantWriteModelByID(ctx, grant.GrantID, grant.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingGrant.WriteModel)
|
||||
|
||||
if reflect.DeepEqual(existingGrant.RoleKeys, grant.RoleKeys) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-0o0pL", "Errors.NoChangesFoundc")
|
||||
}
|
||||
|
||||
events := []eventstore.EventPusher{
|
||||
project.NewGrantChangedEvent(ctx, projectAgg, grant.GrantID, grant.RoleKeys),
|
||||
}
|
||||
|
||||
removedRoles := domain.GetRemovedRoles(existingGrant.RoleKeys, grant.RoleKeys)
|
||||
if len(removedRoles) == 0 {
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingGrant, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectGrantWriteModelToProjectGrant(existingGrant), nil
|
||||
}
|
||||
|
||||
for _, userGrantID := range cascadeUserGrantIDs {
|
||||
event, err := r.removeRoleFromUserGrant(ctx, userGrantID, removedRoles, true)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingGrant, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectGrantWriteModelToProjectGrant(existingGrant), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) removeRoleFromProjectGrant(ctx context.Context, projectAgg *eventstore.Aggregate, projectID, projectGrantID, roleKey string, cascade bool) (_ eventstore.EventPusher, _ *ProjectGrantWriteModel, err error) {
|
||||
existingProjectGrant, err := r.projectGrantWriteModelByID(ctx, projectID, projectGrantID, "")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if existingProjectGrant.State == domain.ProjectGrantStateUnspecified || existingProjectGrant.State == domain.ProjectGrantStateRemoved {
|
||||
return nil, nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.Project.Grant.NotFound")
|
||||
}
|
||||
keyExists := false
|
||||
for i, key := range existingProjectGrant.RoleKeys {
|
||||
if key == roleKey {
|
||||
keyExists = true
|
||||
copy(existingProjectGrant.RoleKeys[i:], existingProjectGrant.RoleKeys[i+1:])
|
||||
existingProjectGrant.RoleKeys[len(existingProjectGrant.RoleKeys)-1] = ""
|
||||
existingProjectGrant.RoleKeys = existingProjectGrant.RoleKeys[:len(existingProjectGrant.RoleKeys)-1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !keyExists {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5m8g9", "Errors.Project.Grant.RoleKeyNotFound")
|
||||
}
|
||||
changedProjectGrant := NewProjectGrantWriteModel(projectGrantID, projectID, existingProjectGrant.ResourceOwner)
|
||||
|
||||
if cascade {
|
||||
return project.NewGrantCascadeChangedEvent(ctx, projectAgg, projectGrantID, existingProjectGrant.RoleKeys), changedProjectGrant, nil
|
||||
}
|
||||
|
||||
return project.NewGrantChangedEvent(ctx, projectAgg, projectGrantID, existingProjectGrant.RoleKeys), changedProjectGrant, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) DeactivateProjectGrant(ctx context.Context, projectID, grantID, resourceOwner string) (err error) {
|
||||
if grantID == "" || projectID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "PROJECT-p0s4V", "Errors.IDMissing")
|
||||
}
|
||||
err = r.checkProjectExists(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingGrant, err := r.projectGrantWriteModelByID(ctx, grantID, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingGrant.State != domain.ProjectGrantStateActive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "PROJECT-47fu8", "Errors.Project.Grant.NotActive")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingGrant.WriteModel)
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewGrantDeactivateEvent(ctx, projectAgg, grantID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) ReactivateProjectGrant(ctx context.Context, projectID, grantID, resourceOwner string) (err error) {
|
||||
if grantID == "" || projectID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "PROJECT-p0s4V", "Errors.IDMissing")
|
||||
}
|
||||
err = r.checkProjectExists(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingGrant, err := r.projectGrantWriteModelByID(ctx, grantID, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingGrant.State != domain.ProjectGrantStateInactive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "PROJECT-47fu8", "Errors.Project.Grant.NotInactive")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingGrant.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewGrantReactivatedEvent(ctx, projectAgg, grantID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveProjectGrant(ctx context.Context, projectID, grantID, resourceOwner string, cascadeUserGrantIDs ...string) (err error) {
|
||||
if grantID == "" || projectID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "PROJECT-1m9fJ", "Errors.IDMissing")
|
||||
}
|
||||
err = r.checkProjectExists(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingGrant, err := r.projectGrantWriteModelByID(ctx, grantID, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events := make([]eventstore.EventPusher, 0)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingGrant.WriteModel)
|
||||
events = append(events, project.NewGrantRemovedEvent(ctx, projectAgg, grantID, existingGrant.GrantedOrgID, projectID))
|
||||
|
||||
for _, userGrantID := range cascadeUserGrantIDs {
|
||||
event, err := r.removeUserGrant(ctx, userGrantID, "", true)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-3m8sG", "usergrantid", grantID).WithError(err).Warn("could not cascade remove user grant")
|
||||
continue
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) projectGrantWriteModelByID(ctx context.Context, grantID, projectID, resourceOwner string) (member *ProjectGrantWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewProjectGrantWriteModel(grantID, projectID, resourceOwner)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if writeModel.State == domain.ProjectGrantStateUnspecified || writeModel.State == domain.ProjectGrantStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "PROJECT-D8JxR", "Errors.Project.Grant.NotFound")
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,102 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddProjectGrantMember(ctx context.Context, member *domain.ProjectGrantMember, resourceOwner string) (*domain.ProjectGrantMember, error) {
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-8fi7G", "Errors.Project.Member.Invalid")
|
||||
}
|
||||
err := r.checkUserExists(ctx, member.UserID, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedMember := NewProjectGrantMemberWriteModel(member.AggregateID, member.UserID, member.GrantID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, addedMember)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedMember.State == domain.MemberStateActive {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-16dVN", "Errors.Project.Member.AlreadyExists")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedMember.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(
|
||||
ctx,
|
||||
project.NewProjectGrantMemberAddedEvent(ctx, projectAgg, member.AggregateID, member.UserID, member.GrantID, member.Roles...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToProjectGrantMember(addedMember), nil
|
||||
}
|
||||
|
||||
//ChangeProjectGrantMember updates an existing member
|
||||
func (r *CommandSide) ChangeProjectGrantMember(ctx context.Context, member *domain.ProjectGrantMember, resourceOwner string) (*domain.ProjectGrantMember, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-109fs", "Errors.Project.Member.Invalid")
|
||||
}
|
||||
|
||||
existingMember, err := r.projectGrantMemberWriteModelByID(ctx, member.AggregateID, member.UserID, member.GrantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(existingMember.Roles, member.Roles) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-2n8vx", "Errors.Project.Member.RolesNotChanged")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingMember.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(
|
||||
ctx,
|
||||
project.NewProjectGrantMemberChangedEvent(ctx, projectAgg, member.UserID, member.GrantID, member.Roles...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToProjectGrantMember(existingMember), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveProjectGrantMember(ctx context.Context, projectID, userID, grantID, resourceOwner string) error {
|
||||
m, err := r.projectGrantMemberWriteModelByID(ctx, projectID, userID, grantID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&m.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewProjectGrantMemberRemovedEvent(ctx, projectAgg, projectID, userID, grantID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) projectGrantMemberWriteModelByID(ctx context.Context, projectID, userID, grantID string) (member *ProjectGrantMemberWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewProjectGrantMemberWriteModel(projectID, userID, grantID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if writeModel.State == domain.MemberStateUnspecified || writeModel.State == domain.MemberStateRemoved {
|
||||
return nil, errors.ThrowNotFound(nil, "PROJECT-37fug", "Errors.NotFound")
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type ProjectGrantMemberWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
GrantID string
|
||||
UserID string
|
||||
Roles []string
|
||||
|
||||
State domain.MemberState
|
||||
}
|
||||
|
||||
func NewProjectGrantMemberWriteModel(projectID, userID, grantID string) *ProjectGrantMemberWriteModel {
|
||||
return &ProjectGrantMemberWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
},
|
||||
UserID: userID,
|
||||
GrantID: grantID,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.GrantMemberAddedEvent:
|
||||
if e.UserID != wm.UserID || e.GrantID != wm.GrantID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.GrantMemberChangedEvent:
|
||||
if e.UserID != wm.UserID || e.GrantID != wm.GrantID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.GrantMemberRemovedEvent:
|
||||
if e.UserID != wm.UserID || e.GrantID != wm.GrantID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.GrantRemovedEvent:
|
||||
if e.GrantID != wm.GrantID {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantMemberWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.GrantMemberAddedEvent:
|
||||
wm.Roles = e.Roles
|
||||
wm.State = domain.MemberStateActive
|
||||
case *project.GrantMemberChangedEvent:
|
||||
wm.Roles = e.Roles
|
||||
case *project.GrantMemberRemovedEvent:
|
||||
wm.State = domain.MemberStateRemoved
|
||||
case *project.GrantRemovedEvent, *project.ProjectRemovedEvent:
|
||||
wm.State = domain.MemberStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
project.GrantMemberAddedType,
|
||||
project.GrantMemberChangedType,
|
||||
project.GrantMemberRemovedType,
|
||||
project.GrantRemovedType,
|
||||
project.ProjectRemovedType)
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type ProjectGrantWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
GrantID string
|
||||
GrantedOrgID string
|
||||
RoleKeys []string
|
||||
State domain.ProjectGrantState
|
||||
}
|
||||
|
||||
func NewProjectGrantWriteModel(grantID, projectID, resourceOwner string) *ProjectGrantWriteModel {
|
||||
return &ProjectGrantWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
GrantID: grantID,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.GrantAddedEvent:
|
||||
if e.GrantID == wm.GrantID {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantChangedEvent:
|
||||
if e.GrantID == wm.GrantID {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantCascadeChangedEvent:
|
||||
if e.GrantID == wm.GrantID {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantDeactivateEvent:
|
||||
if e.GrantID == wm.GrantID {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantReactivatedEvent:
|
||||
if e.GrantID == wm.GrantID {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.GrantRemovedEvent:
|
||||
if e.GrantID == wm.GrantID {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.GrantAddedEvent:
|
||||
wm.GrantID = e.GrantID
|
||||
wm.GrantedOrgID = e.GrantedOrgID
|
||||
wm.RoleKeys = e.RoleKeys
|
||||
wm.State = domain.ProjectGrantStateActive
|
||||
case *project.GrantChangedEvent:
|
||||
wm.RoleKeys = e.RoleKeys
|
||||
case *project.GrantCascadeChangedEvent:
|
||||
wm.RoleKeys = e.RoleKeys
|
||||
case *project.GrantDeactivateEvent:
|
||||
if wm.State == domain.ProjectGrantStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.ProjectGrantStateInactive
|
||||
case *project.GrantReactivatedEvent:
|
||||
if wm.State == domain.ProjectGrantStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.ProjectGrantStateActive
|
||||
case *project.GrantRemovedEvent:
|
||||
wm.State = domain.ProjectGrantStateRemoved
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.State = domain.ProjectGrantStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ProjectGrantWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
project.GrantAddedType,
|
||||
project.GrantChangedType,
|
||||
project.GrantCascadeChangedType,
|
||||
project.GrantDeactivatedType,
|
||||
project.GrantReactivatedType,
|
||||
project.GrantRemovedType,
|
||||
project.ProjectRemovedType)
|
||||
if wm.ResourceOwner != "" {
|
||||
query.ResourceOwner(wm.ResourceOwner)
|
||||
}
|
||||
return query
|
||||
}
|
@@ -1,116 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddProjectMember(ctx context.Context, member *domain.Member, resourceOwner string) (*domain.Member, error) {
|
||||
addedMember := NewProjectMemberWriteModel(member.AggregateID, member.UserID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedMember.WriteModel)
|
||||
event, err := r.addProjectMember(ctx, projectAgg, addedMember, member)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addProjectMember(ctx context.Context, projectAgg *eventstore.Aggregate, addedMember *ProjectMemberWriteModel, member *domain.Member) (eventstore.EventPusher, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-W8m4l", "Errors.Project.Member.Invalid")
|
||||
}
|
||||
|
||||
err := r.checkUserExists(ctx, addedMember.UserID, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, addedMember)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedMember.State == domain.MemberStateActive {
|
||||
return nil, errors.ThrowAlreadyExists(nil, "PROJECT-PtXi1", "Errors.Project.Member.AlreadyExists")
|
||||
}
|
||||
|
||||
return project.NewProjectMemberAddedEvent(ctx, projectAgg, member.UserID, member.Roles...), nil
|
||||
}
|
||||
|
||||
//ChangeProjectMember updates an existing member
|
||||
func (r *CommandSide) ChangeProjectMember(ctx context.Context, member *domain.Member, resourceOwner string) (*domain.Member, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-LiaZi", "Errors.Project.Member.Invalid")
|
||||
}
|
||||
|
||||
existingMember, err := r.projectMemberWriteModelByID(ctx, member.AggregateID, member.UserID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(existingMember.Roles, member.Roles) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-LiaZi", "Errors.Project.Member.RolesNotChanged")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingMember.MemberWriteModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, project.NewProjectMemberChangedEvent(ctx, projectAgg, member.UserID, member.Roles...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = AppendAndReduce(existingMember, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveProjectMember(ctx context.Context, projectID, userID, resourceOwner string) error {
|
||||
m, err := r.projectMemberWriteModelByID(ctx, projectID, userID, resourceOwner)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
|
||||
_, err = r.eventstore.PushEvents(ctx, project.NewProjectMemberRemovedEvent(ctx, projectAgg, userID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) projectMemberWriteModelByID(ctx context.Context, projectID, userID, resourceOwner string) (member *ProjectMemberWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewProjectMemberWriteModel(projectID, userID, resourceOwner)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if writeModel.State == domain.MemberStateUnspecified || writeModel.State == domain.MemberStateRemoved {
|
||||
return nil, errors.ThrowNotFound(nil, "PROJECT-D8JxR", "Errors.NotFound")
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type ProjectMemberWriteModel struct {
|
||||
MemberWriteModel
|
||||
}
|
||||
|
||||
func NewProjectMemberWriteModel(projectID, userID, resourceOwner string) *ProjectMemberWriteModel {
|
||||
return &ProjectMemberWriteModel{
|
||||
MemberWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
UserID: userID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.MemberAddedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberAddedEvent)
|
||||
case *project.MemberChangedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberChangedEvent)
|
||||
case *project.MemberRemovedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectMemberWriteModel) Reduce() error {
|
||||
return wm.MemberWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ProjectMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.MemberWriteModel.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(project.MemberAddedType,
|
||||
project.MemberChangedType,
|
||||
project.MemberRemovedType)
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type ProjectWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Name string
|
||||
ProjectRoleAssertion bool
|
||||
ProjectRoleCheck bool
|
||||
State domain.ProjectState
|
||||
}
|
||||
|
||||
func NewProjectWriteModel(projectID string, resourceOwner string) *ProjectWriteModel {
|
||||
return &ProjectWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.ProjectAddedEvent:
|
||||
wm.Name = e.Name
|
||||
wm.ProjectRoleAssertion = e.ProjectRoleAssertion
|
||||
wm.ProjectRoleCheck = e.ProjectRoleCheck
|
||||
wm.State = domain.ProjectStateActive
|
||||
case *project.ProjectChangeEvent:
|
||||
if e.Name != nil {
|
||||
wm.Name = *e.Name
|
||||
}
|
||||
if e.ProjectRoleAssertion != nil {
|
||||
wm.ProjectRoleAssertion = *e.ProjectRoleAssertion
|
||||
}
|
||||
if e.ProjectRoleCheck != nil {
|
||||
wm.ProjectRoleCheck = *e.ProjectRoleCheck
|
||||
}
|
||||
case *project.ProjectDeactivatedEvent:
|
||||
if wm.State == domain.ProjectStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.ProjectStateInactive
|
||||
case *project.ProjectReactivatedEvent:
|
||||
if wm.State == domain.ProjectStateRemoved {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.ProjectStateActive
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.State = domain.ProjectStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ProjectWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(project.ProjectAddedType,
|
||||
project.ProjectChangedType,
|
||||
project.ProjectDeactivatedType,
|
||||
project.ProjectReactivatedType,
|
||||
project.ProjectRemovedType)
|
||||
}
|
||||
|
||||
func (wm *ProjectWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
name string,
|
||||
projectRoleAssertion,
|
||||
projectRoleCheck bool,
|
||||
) (*project.ProjectChangeEvent, bool, error) {
|
||||
changes := make([]project.ProjectChanges, 0)
|
||||
var err error
|
||||
|
||||
oldName := ""
|
||||
if wm.Name != name {
|
||||
oldName = wm.Name
|
||||
changes = append(changes, project.ChangeName(name))
|
||||
}
|
||||
if wm.ProjectRoleAssertion != projectRoleAssertion {
|
||||
changes = append(changes, project.ChangeProjectRoleAssertion(projectRoleAssertion))
|
||||
}
|
||||
if wm.ProjectRoleCheck != projectRoleCheck {
|
||||
changes = append(changes, project.ChangeProjectRoleCheck(projectRoleCheck))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := project.NewProjectChangeEvent(ctx, aggregate, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
||||
|
||||
func ProjectAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
|
||||
return eventstore.AggregateFromWriteModel(wm, project.AggregateType, project.AggregateVersion)
|
||||
}
|
@@ -1,154 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddProjectRole(ctx context.Context, projectRole *domain.ProjectRole, resourceOwner string) (_ *domain.ProjectRole, err error) {
|
||||
err = r.checkProjectExists(ctx, projectRole.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roleWriteModel := NewProjectRoleWriteModelWithKey(projectRole.Key, projectRole.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&roleWriteModel.WriteModel)
|
||||
events, err := r.addProjectRoles(ctx, projectAgg, projectRole.AggregateID, projectRole)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(roleWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return roleWriteModelToRole(roleWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) BulkAddProjectRole(ctx context.Context, projectID, resourceOwner string, projectRoles []*domain.ProjectRole) (err error) {
|
||||
err = r.checkProjectExists(ctx, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
roleWriteModel := NewProjectRoleWriteModel(projectID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&roleWriteModel.WriteModel)
|
||||
events, err := r.addProjectRoles(ctx, projectAgg, projectID, projectRoles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) addProjectRoles(ctx context.Context, projectAgg *eventstore.Aggregate, projectID string, projectRoles ...*domain.ProjectRole) ([]eventstore.EventPusher, error) {
|
||||
var events []eventstore.EventPusher
|
||||
for _, projectRole := range projectRoles {
|
||||
if !projectRole.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4m9vS", "Errors.Project.Invalid")
|
||||
}
|
||||
events = append(events, project.NewRoleAddedEvent(
|
||||
ctx,
|
||||
projectAgg,
|
||||
projectRole.Key,
|
||||
projectRole.DisplayName,
|
||||
projectRole.Group,
|
||||
projectID,
|
||||
))
|
||||
}
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeProjectRole(ctx context.Context, projectRole *domain.ProjectRole, resourceOwner string) (_ *domain.ProjectRole, err error) {
|
||||
if !projectRole.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4m9vS", "Errors.Project.Invalid")
|
||||
}
|
||||
err = r.checkProjectExists(ctx, projectRole.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingRole, err := r.getProjectRoleWriteModelByID(ctx, projectRole.Key, projectRole.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingRole.State == domain.ProjectRoleStateUnspecified || existingRole.State == domain.ProjectRoleStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-vv8M9", "Errors.Project.Role.NotExisting")
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingRole.WriteModel)
|
||||
|
||||
changeEvent, changed, err := existingRole.NewProjectRoleChangedEvent(ctx, projectAgg, projectRole.Key, projectRole.DisplayName, projectRole.Group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !changed {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5M0cs", "Errors.NoChangesFound")
|
||||
}
|
||||
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, changeEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingRole, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return roleWriteModelToRole(existingRole), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveProjectRole(ctx context.Context, projectID, key, resourceOwner string, cascadingProjectGrantIds []string, cascadeUserGrantIDs ...string) (err error) {
|
||||
if projectID == "" || key == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4m9vS", "Errors.Project.Role.Invalid")
|
||||
}
|
||||
existingRole, err := r.getProjectRoleWriteModelByID(ctx, key, projectID, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingRole.State == domain.ProjectRoleStateUnspecified || existingRole.State == domain.ProjectRoleStateRemoved {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-m9vMf", "Errors.Project.Role.NotExisting")
|
||||
}
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingRole.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
project.NewRoleRemovedEvent(ctx, projectAgg, key, projectID),
|
||||
}
|
||||
|
||||
for _, projectGrantID := range cascadingProjectGrantIds {
|
||||
event, _, err := r.removeRoleFromProjectGrant(ctx, projectAgg, projectID, projectGrantID, key, true)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-6n77g", "projectgrantid", projectGrantID).WithError(err).Warn("could not cascade remove role from project grant")
|
||||
continue
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
|
||||
for _, grantID := range cascadeUserGrantIDs {
|
||||
event, err := r.removeRoleFromUserGrant(ctx, grantID, []string{key}, true)
|
||||
if err != nil {
|
||||
logging.LogWithFields("COMMAND-mK0of", "usergrantid", grantID).WithError(err).Warn("could not cascade remove role on user grant")
|
||||
continue
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) getProjectRoleWriteModelByID(ctx context.Context, key, projectID, resourceOwner string) (*ProjectRoleWriteModel, error) {
|
||||
projectRoleWriteModel := NewProjectRoleWriteModelWithKey(key, projectID, resourceOwner)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, projectRoleWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectRoleWriteModel, nil
|
||||
}
|
@@ -1,120 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type ProjectRoleWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Key string
|
||||
DisplayName string
|
||||
Group string
|
||||
State domain.ProjectRoleState
|
||||
}
|
||||
|
||||
func NewProjectRoleWriteModelWithKey(key, projectID, resourceOwner string) *ProjectRoleWriteModel {
|
||||
return &ProjectRoleWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
Key: key,
|
||||
}
|
||||
}
|
||||
|
||||
func NewProjectRoleWriteModel(projectID, resourceOwner string) *ProjectRoleWriteModel {
|
||||
return &ProjectRoleWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: projectID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectRoleWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *project.RoleAddedEvent:
|
||||
if e.Key == wm.Key {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.RoleChangedEvent:
|
||||
if e.Key == wm.Key {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.RoleRemovedEvent:
|
||||
if e.Key == wm.Key {
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ProjectRoleWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *project.RoleAddedEvent:
|
||||
wm.Key = e.Key
|
||||
wm.DisplayName = e.DisplayName
|
||||
wm.Group = e.Group
|
||||
wm.State = domain.ProjectRoleStateActive
|
||||
case *project.RoleChangedEvent:
|
||||
wm.Key = e.Key
|
||||
if e.DisplayName != nil {
|
||||
wm.DisplayName = *e.DisplayName
|
||||
}
|
||||
if e.Group != nil {
|
||||
wm.Group = *e.Group
|
||||
}
|
||||
case *project.RoleRemovedEvent:
|
||||
wm.State = domain.ProjectRoleStateRemoved
|
||||
case *project.ProjectRemovedEvent:
|
||||
wm.State = domain.ProjectRoleStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ProjectRoleWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
EventTypes(
|
||||
project.RoleAddedType,
|
||||
project.RoleChangedType,
|
||||
project.RoleRemovedType,
|
||||
project.ProjectRemovedType)
|
||||
}
|
||||
|
||||
func (wm *ProjectRoleWriteModel) NewProjectRoleChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
key,
|
||||
displayName,
|
||||
group string,
|
||||
) (*project.RoleChangedEvent, bool, error) {
|
||||
changes := make([]project.RoleChanges, 0)
|
||||
var err error
|
||||
changes = append(changes, project.ChangeKey(key))
|
||||
|
||||
if wm.DisplayName != displayName {
|
||||
changes = append(changes, project.ChangeDisplayName(displayName))
|
||||
}
|
||||
if wm.Group != group {
|
||||
changes = append(changes, project.ChangeGroup(group))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := project.NewRoleChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
@@ -1,101 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
type Step interface {
|
||||
Step() domain.Step
|
||||
execute(context.Context, *CommandSide) error
|
||||
}
|
||||
|
||||
const (
|
||||
SetupUser = "SETUP"
|
||||
)
|
||||
|
||||
func (r *CommandSide) ExecuteSetupSteps(ctx context.Context, steps []Step) error {
|
||||
iam, err := r.GetIAM(ctx)
|
||||
if err != nil && !caos_errs.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if iam != nil && (iam.SetUpDone == domain.StepCount-1 || iam.SetUpStarted != iam.SetUpDone) {
|
||||
logging.Log("COMMA-dgd2z").Info("all steps done")
|
||||
return nil
|
||||
}
|
||||
|
||||
if iam == nil {
|
||||
iam = &domain.IAM{ObjectRoot: models.ObjectRoot{}}
|
||||
}
|
||||
|
||||
ctx = setSetUpContextData(ctx)
|
||||
|
||||
for _, step := range steps {
|
||||
iam, err = r.StartSetup(ctx, step.Step())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = step.execute(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSetUpContextData(ctx context.Context) context.Context {
|
||||
return authz.SetCtxData(ctx, authz.CtxData{UserID: SetupUser})
|
||||
}
|
||||
|
||||
func (r *CommandSide) StartSetup(ctx context.Context, step domain.Step) (*domain.IAM, error) {
|
||||
iamWriteModel, err := r.getIAMWriteModel(ctx)
|
||||
if err != nil && !caos_errs.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
if iamWriteModel.SetUpStarted >= step || iamWriteModel.SetUpStarted != iamWriteModel.SetUpDone {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "setup error")
|
||||
}
|
||||
aggregate := IAMAggregateFromWriteModel(&iamWriteModel.WriteModel)
|
||||
pushedEvents, err := r.eventstore.PushEvents(ctx, iam_repo.NewSetupStepStartedEvent(ctx, aggregate, step))
|
||||
if err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-Grgh1", "Setup start failed")
|
||||
}
|
||||
err = AppendAndReduce(iamWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logging.LogWithFields("SETUP-fhh21", "step", step).Info("setup step started")
|
||||
return writeModelToIAM(iamWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) setup(ctx context.Context, step Step, iamAggregateProvider func(*IAMWriteModel) ([]eventstore.EventPusher, error)) error {
|
||||
iam, err := r.getIAMWriteModel(ctx)
|
||||
if err != nil && !caos_errs.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if iam.SetUpStarted != step.Step() && iam.SetUpDone+1 != step.Step() {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Dge32", "wrong step")
|
||||
}
|
||||
events, err := iamAggregateProvider(iam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||
events = append(events, iam_repo.NewSetupStepDoneEvent(ctx, iamAgg, step.Step()))
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return caos_errs.ThrowPreconditionFailedf(nil, "EVENT-dbG31", "Setup %v failed", step.Step())
|
||||
}
|
||||
logging.LogWithFields("SETUP-Sg1t1", "step", step.Step()).Info("setup step done")
|
||||
return nil
|
||||
}
|
@@ -1,271 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
const (
|
||||
OIDCResponseTypeCode = "CODE"
|
||||
OIDCResponseTypeIDToken = "ID_TOKEN"
|
||||
OIDCResponseTypeToken = "ID_TOKEN TOKEN"
|
||||
OIDCGrantTypeAuthorizationCode = "AUTHORIZATION_CODE"
|
||||
OIDCGrantTypeImplicit = "IMPLICIT"
|
||||
OIDCGrantTypeRefreshToken = "REFRESH_TOKEN"
|
||||
OIDCApplicationTypeNative = "NATIVE"
|
||||
OIDCApplicationTypeUserAgent = "USER_AGENT"
|
||||
OIDCApplicationTypeWeb = "WEB"
|
||||
OIDCAuthMethodTypeNone = "NONE"
|
||||
OIDCAuthMethodTypeBasic = "BASIC"
|
||||
OIDCAuthMethodTypePost = "POST"
|
||||
)
|
||||
|
||||
type Step1 struct {
|
||||
GlobalOrg string
|
||||
IAMProject string
|
||||
DefaultLoginPolicy LoginPolicy
|
||||
Orgs []Org
|
||||
}
|
||||
|
||||
func (s *Step1) Step() domain.Step {
|
||||
return domain.Step1
|
||||
}
|
||||
|
||||
func (s *Step1) execute(ctx context.Context, commandSide *CommandSide) error {
|
||||
return commandSide.SetupStep1(ctx, s)
|
||||
}
|
||||
|
||||
type LoginPolicy struct {
|
||||
AllowRegister bool
|
||||
AllowUsernamePassword bool
|
||||
AllowExternalIdp bool
|
||||
}
|
||||
|
||||
type User struct {
|
||||
FirstName string
|
||||
LastName string
|
||||
UserName string
|
||||
Email string
|
||||
Password string
|
||||
}
|
||||
|
||||
type Org struct {
|
||||
Name string
|
||||
Domain string
|
||||
OrgIamPolicy bool
|
||||
Owner User
|
||||
Projects []Project
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
Name string
|
||||
Users []User
|
||||
Members []string
|
||||
OIDCApps []OIDCApp
|
||||
}
|
||||
|
||||
type OIDCApp struct {
|
||||
Name string
|
||||
RedirectUris []string
|
||||
ResponseTypes []string
|
||||
GrantTypes []string
|
||||
ApplicationType string
|
||||
AuthMethodType string
|
||||
PostLogoutRedirectUris []string
|
||||
DevMode bool
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetupStep1(ctx context.Context, step1 *Step1) error {
|
||||
var events []eventstore.EventPusher
|
||||
iamWriteModel := NewIAMWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&iamWriteModel.WriteModel)
|
||||
//create default login policy
|
||||
loginPolicyEvent, err := r.addDefaultLoginPolicy(ctx, iamAgg, NewIAMLoginPolicyWriteModel(),
|
||||
&domain.LoginPolicy{
|
||||
AllowUsernamePassword: step1.DefaultLoginPolicy.AllowUsernamePassword,
|
||||
AllowRegister: step1.DefaultLoginPolicy.AllowRegister,
|
||||
AllowExternalIDP: step1.DefaultLoginPolicy.AllowExternalIdp,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, loginPolicyEvent)
|
||||
logging.Log("SETUP-sd2hj").Info("default login policy set up")
|
||||
//create orgs
|
||||
for _, organisation := range step1.Orgs {
|
||||
orgAgg, humanWriteModel, _, setUpOrgEvents, err := r.setUpOrg(ctx,
|
||||
&domain.Org{
|
||||
Name: organisation.Name,
|
||||
Domains: []*domain.OrgDomain{{Domain: organisation.Domain}},
|
||||
},
|
||||
&domain.Human{
|
||||
Username: organisation.Owner.UserName,
|
||||
Profile: &domain.Profile{
|
||||
FirstName: organisation.Owner.FirstName,
|
||||
LastName: organisation.Owner.LastName,
|
||||
},
|
||||
Password: &domain.Password{
|
||||
SecretString: organisation.Owner.Password,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: organisation.Owner.Email,
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, setUpOrgEvents...)
|
||||
logging.LogWithFields("SETUP-Gdsfg", "id", orgAgg.ID, "name", organisation.Name).Info("org set up")
|
||||
|
||||
if organisation.OrgIamPolicy {
|
||||
orgIAMPolicyEvent, err := r.addOrgIAMPolicy(ctx, orgAgg, NewORGOrgIAMPolicyWriteModel(orgAgg.ID), &domain.OrgIAMPolicy{UserLoginMustBeDomain: false})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, orgIAMPolicyEvent)
|
||||
}
|
||||
if organisation.Name == step1.GlobalOrg {
|
||||
globalOrgEvent, err := r.setGlobalOrg(ctx, iamAgg, iamWriteModel, orgAgg.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, globalOrgEvent)
|
||||
logging.Log("SETUP-BDn52").Info("global org set")
|
||||
}
|
||||
//projects
|
||||
for _, proj := range organisation.Projects {
|
||||
project := &domain.Project{Name: proj.Name}
|
||||
projectEvents, projectWriteModel, err := r.addProject(ctx, project, orgAgg.ID, humanWriteModel.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, projectEvents...)
|
||||
if project.Name == step1.IAMProject {
|
||||
iamProjectEvent, err := r.setIAMProject(ctx, iamAgg, iamWriteModel, projectWriteModel.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, iamProjectEvent)
|
||||
logging.Log("SETUP-Bdfs1").Info("IAM project set")
|
||||
iamEvent, err := r.addIAMMember(ctx, iamAgg, NewIAMMemberWriteModel(humanWriteModel.AggregateID), domain.NewMember(iamAgg.ID, humanWriteModel.AggregateID, domain.RoleIAMOwner))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, iamEvent)
|
||||
logging.Log("SETUP-BSf2h").Info("IAM owner set")
|
||||
}
|
||||
//create applications
|
||||
for _, app := range proj.OIDCApps {
|
||||
applicationEvents, err := setUpApplication(ctx, r, projectWriteModel, project, app, orgAgg.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, applicationEvents...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
events = append(events, iam_repo.NewSetupStepDoneEvent(ctx, iamAgg, domain.Step1))
|
||||
|
||||
_, err = r.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Gr2hh", "Setup Step1 failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setUpApplication(ctx context.Context, r *CommandSide, projectWriteModel *ProjectWriteModel, project *domain.Project, oidcApp OIDCApp, resourceOwner string) ([]eventstore.EventPusher, error) {
|
||||
app := &domain.OIDCApp{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: projectWriteModel.AggregateID,
|
||||
},
|
||||
AppName: oidcApp.Name,
|
||||
RedirectUris: oidcApp.RedirectUris,
|
||||
ResponseTypes: getOIDCResponseTypes(oidcApp.ResponseTypes),
|
||||
GrantTypes: getOIDCGrantTypes(oidcApp.GrantTypes),
|
||||
ApplicationType: getOIDCApplicationType(oidcApp.ApplicationType),
|
||||
AuthMethodType: getOIDCAuthMethod(oidcApp.AuthMethodType),
|
||||
DevMode: oidcApp.DevMode,
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&projectWriteModel.WriteModel)
|
||||
events, _, err := r.addOIDCApplication(ctx, projectAgg, project, app, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logging.LogWithFields("SETUP-Edgw4", "name", app.AppName, "clientID", app.ClientID).Info("application set up")
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func getOIDCResponseTypes(responseTypes []string) []domain.OIDCResponseType {
|
||||
types := make([]domain.OIDCResponseType, len(responseTypes))
|
||||
for i, t := range responseTypes {
|
||||
types[i] = getOIDCResponseType(t)
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
func getOIDCResponseType(responseType string) domain.OIDCResponseType {
|
||||
switch responseType {
|
||||
case OIDCResponseTypeCode:
|
||||
return domain.OIDCResponseTypeCode
|
||||
case OIDCResponseTypeIDToken:
|
||||
return domain.OIDCResponseTypeIDToken
|
||||
case OIDCResponseTypeToken:
|
||||
return domain.OIDCResponseTypeIDTokenToken
|
||||
}
|
||||
return domain.OIDCResponseTypeCode
|
||||
}
|
||||
|
||||
func getOIDCGrantTypes(grantTypes []string) []domain.OIDCGrantType {
|
||||
types := make([]domain.OIDCGrantType, len(grantTypes))
|
||||
for i, t := range grantTypes {
|
||||
types[i] = getOIDCGrantType(t)
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
func getOIDCGrantType(grantTypes string) domain.OIDCGrantType {
|
||||
switch grantTypes {
|
||||
case OIDCGrantTypeAuthorizationCode:
|
||||
return domain.OIDCGrantTypeAuthorizationCode
|
||||
case OIDCGrantTypeImplicit:
|
||||
return domain.OIDCGrantTypeImplicit
|
||||
case OIDCGrantTypeRefreshToken:
|
||||
return domain.OIDCGrantTypeRefreshToken
|
||||
}
|
||||
return domain.OIDCGrantTypeAuthorizationCode
|
||||
}
|
||||
|
||||
func getOIDCApplicationType(appType string) domain.OIDCApplicationType {
|
||||
switch appType {
|
||||
case OIDCApplicationTypeNative:
|
||||
return domain.OIDCApplicationTypeNative
|
||||
case OIDCApplicationTypeUserAgent:
|
||||
return domain.OIDCApplicationTypeUserAgent
|
||||
case OIDCApplicationTypeWeb:
|
||||
return domain.OIDCApplicationTypeWeb
|
||||
}
|
||||
return domain.OIDCApplicationTypeWeb
|
||||
}
|
||||
|
||||
func getOIDCAuthMethod(authMethod string) domain.OIDCAuthMethodType {
|
||||
switch authMethod {
|
||||
case OIDCAuthMethodTypeNone:
|
||||
return domain.OIDCAuthMethodTypeNone
|
||||
case OIDCAuthMethodTypeBasic:
|
||||
return domain.OIDCAuthMethodTypeBasic
|
||||
case OIDCAuthMethodTypePost:
|
||||
return domain.OIDCAuthMethodTypePost
|
||||
}
|
||||
return domain.OIDCAuthMethodTypeBasic
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
type Step10 struct {
|
||||
DefaultMailTemplate domain.MailTemplate
|
||||
DefaultMailTexts []domain.MailText
|
||||
}
|
||||
|
||||
func (s *Step10) Step() domain.Step {
|
||||
return domain.Step10
|
||||
}
|
||||
|
||||
func (s *Step10) execute(ctx context.Context, commandSide *CommandSide) error {
|
||||
return commandSide.SetupStep10(ctx, s)
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetupStep10(ctx context.Context, step *Step10) error {
|
||||
fn := func(iam *IAMWriteModel) ([]eventstore.EventPusher, error) {
|
||||
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||
mailTemplateEvent, err := r.addDefaultMailTemplate(ctx, iamAgg, NewIAMMailTemplateWriteModel(), &step.DefaultMailTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events := []eventstore.EventPusher{
|
||||
mailTemplateEvent,
|
||||
}
|
||||
for _, text := range step.DefaultMailTexts {
|
||||
defaultTextEvent, err := r.addDefaultMailText(ctx, iamAgg, NewIAMMailTextWriteModel(text.MailTextType, text.Language), &text)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events = append(events, defaultTextEvent)
|
||||
}
|
||||
logging.Log("SETUP-3N9fs").Info("default mail template/text set up")
|
||||
return events, nil
|
||||
}
|
||||
return r.setup(ctx, step, fn)
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
type Step11 struct {
|
||||
MigrateV1EventstoreToV2 bool
|
||||
}
|
||||
|
||||
func (s *Step11) Step() domain.Step {
|
||||
return domain.Step11
|
||||
}
|
||||
|
||||
func (s *Step11) execute(ctx context.Context, commandSide *CommandSide) error {
|
||||
return commandSide.SetupStep11(ctx, s)
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetupStep11(ctx context.Context, step *Step11) error {
|
||||
fn := func(iam *IAMWriteModel) ([]eventstore.EventPusher, error) {
|
||||
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||
var uniqueContraintMigrations []*domain.UniqueConstraintMigration
|
||||
if step.MigrateV1EventstoreToV2 {
|
||||
uniqueConstraints := NewUniqueConstraintReadModel(ctx, r)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, uniqueConstraints)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniqueContraintMigrations = uniqueConstraints.UniqueConstraints
|
||||
}
|
||||
logging.Log("SETUP-M9fsd").Info("migrate v1 eventstore to v2")
|
||||
return []eventstore.EventPusher{iam_repo.NewMigrateUniqueConstraintEvent(ctx, iamAgg, uniqueContraintMigrations)}, nil
|
||||
}
|
||||
return r.setup(ctx, step, fn)
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
type Step2 struct {
|
||||
DefaultPasswordComplexityPolicy iam_model.PasswordComplexityPolicy
|
||||
}
|
||||
|
||||
func (s *Step2) Step() domain.Step {
|
||||
return domain.Step2
|
||||
}
|
||||
|
||||
func (s *Step2) execute(ctx context.Context, commandSide *CommandSide) error {
|
||||
return commandSide.SetupStep2(ctx, s)
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetupStep2(ctx context.Context, step *Step2) error {
|
||||
fn := func(iam *IAMWriteModel) ([]eventstore.EventPusher, error) {
|
||||
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||
event, err := r.addDefaultPasswordComplexityPolicy(ctx, iamAgg, NewIAMPasswordComplexityPolicyWriteModel(), &domain.PasswordComplexityPolicy{
|
||||
MinLength: step.DefaultPasswordComplexityPolicy.MinLength,
|
||||
HasLowercase: step.DefaultPasswordComplexityPolicy.HasLowercase,
|
||||
HasUppercase: step.DefaultPasswordComplexityPolicy.HasUppercase,
|
||||
HasNumber: step.DefaultPasswordComplexityPolicy.HasNumber,
|
||||
HasSymbol: step.DefaultPasswordComplexityPolicy.HasSymbol,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logging.Log("SETUP-ADgd2").Info("default password complexity policy set up")
|
||||
return []eventstore.EventPusher{event}, nil
|
||||
}
|
||||
return r.setup(ctx, step, fn)
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
type Step3 struct {
|
||||
DefaultPasswordAgePolicy iam_model.PasswordAgePolicy
|
||||
}
|
||||
|
||||
func (s *Step3) Step() domain.Step {
|
||||
return domain.Step3
|
||||
}
|
||||
|
||||
func (s *Step3) execute(ctx context.Context, commandSide *CommandSide) error {
|
||||
return commandSide.SetupStep3(ctx, s)
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetupStep3(ctx context.Context, step *Step3) error {
|
||||
fn := func(iam *IAMWriteModel) ([]eventstore.EventPusher, error) {
|
||||
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||
event, err := r.addDefaultPasswordAgePolicy(ctx, iamAgg, NewIAMPasswordAgePolicyWriteModel(), &domain.PasswordAgePolicy{
|
||||
MaxAgeDays: step.DefaultPasswordAgePolicy.MaxAgeDays,
|
||||
ExpireWarnDays: step.DefaultPasswordAgePolicy.ExpireWarnDays,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logging.Log("SETUP-DBqgq").Info("default password age policy set up")
|
||||
return []eventstore.EventPusher{event}, nil
|
||||
}
|
||||
return r.setup(ctx, step, fn)
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
type Step4 struct {
|
||||
DefaultPasswordLockoutPolicy iam_model.PasswordLockoutPolicy
|
||||
}
|
||||
|
||||
func (s *Step4) Step() domain.Step {
|
||||
return domain.Step4
|
||||
}
|
||||
|
||||
func (s *Step4) execute(ctx context.Context, commandSide *CommandSide) error {
|
||||
return commandSide.SetupStep4(ctx, s)
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetupStep4(ctx context.Context, step *Step4) error {
|
||||
fn := func(iam *IAMWriteModel) ([]eventstore.EventPusher, error) {
|
||||
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||
event, err := r.addDefaultPasswordLockoutPolicy(ctx, iamAgg, NewIAMPasswordLockoutPolicyWriteModel(), &domain.PasswordLockoutPolicy{
|
||||
MaxAttempts: step.DefaultPasswordLockoutPolicy.MaxAttempts,
|
||||
ShowLockOutFailures: step.DefaultPasswordLockoutPolicy.ShowLockOutFailures,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logging.Log("SETUP-Bfnge").Info("default password lockout policy set up")
|
||||
return []eventstore.EventPusher{event}, nil
|
||||
}
|
||||
return r.setup(ctx, step, fn)
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
type Step5 struct {
|
||||
DefaultOrgIAMPolicy iam_model.OrgIAMPolicy
|
||||
}
|
||||
|
||||
func (s *Step5) Step() domain.Step {
|
||||
return domain.Step5
|
||||
}
|
||||
|
||||
func (s *Step5) execute(ctx context.Context, commandSide *CommandSide) error {
|
||||
return commandSide.SetupStep5(ctx, s)
|
||||
}
|
||||
|
||||
func (r *CommandSide) SetupStep5(ctx context.Context, step *Step5) error {
|
||||
fn := func(iam *IAMWriteModel) ([]eventstore.EventPusher, error) {
|
||||
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||
event, err := r.addDefaultOrgIAMPolicy(ctx, iamAgg, NewIAMOrgIAMPolicyWriteModel(), &domain.OrgIAMPolicy{
|
||||
UserLoginMustBeDomain: step.DefaultOrgIAMPolicy.UserLoginMustBeDomain,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logging.Log("SETUP-ADgd2").Info("default org iam policy set up")
|
||||
return []eventstore.EventPusher{event}, nil
|
||||
}
|
||||
return r.setup(ctx, step, fn)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user