mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 11:04:25 +00:00
95481c2e0b
* feat: run repeatable setup steps * feat: react to system config changes * renaming
185 lines
6.9 KiB
Go
185 lines
6.9 KiB
Go
package command
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/zitadel/zitadel/internal/command/preparation"
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
"github.com/zitadel/zitadel/internal/repository/instance"
|
|
"github.com/zitadel/zitadel/internal/repository/project"
|
|
)
|
|
|
|
type SystemConfigWriteModel struct {
|
|
eventstore.WriteModel
|
|
|
|
Instances map[string]*systemConfigChangesInstanceModel
|
|
externalDomain string
|
|
externalPort uint16
|
|
externalSecure bool
|
|
newExternalDomain string
|
|
newExternalPort uint16
|
|
newExternalSecure bool
|
|
}
|
|
|
|
type systemConfigChangesInstanceModel struct {
|
|
Domains []string
|
|
GeneratedDomain string
|
|
ProjectID string
|
|
ConsoleAppID string
|
|
RedirectUris []string
|
|
PostLogoutRedirectUris []string
|
|
}
|
|
|
|
func NewSystemConfigWriteModel(externalDomain, newExternalDomain string, externalPort, newExternalPort uint16, externalSecure, newExternalSecure bool) *SystemConfigWriteModel {
|
|
return &SystemConfigWriteModel{
|
|
WriteModel: eventstore.WriteModel{},
|
|
Instances: make(map[string]*systemConfigChangesInstanceModel),
|
|
externalDomain: externalDomain,
|
|
externalPort: externalPort,
|
|
externalSecure: externalSecure,
|
|
newExternalDomain: newExternalDomain,
|
|
newExternalPort: newExternalPort,
|
|
newExternalSecure: newExternalSecure,
|
|
}
|
|
}
|
|
|
|
func (wm *SystemConfigWriteModel) Reduce() error {
|
|
for _, event := range wm.Events {
|
|
switch e := event.(type) {
|
|
case *instance.InstanceAddedEvent:
|
|
wm.Instances[e.Aggregate().InstanceID] = &systemConfigChangesInstanceModel{}
|
|
case *instance.InstanceRemovedEvent:
|
|
delete(wm.Instances, e.Aggregate().InstanceID)
|
|
case *instance.DomainAddedEvent:
|
|
if !e.Generated && e.Domain != wm.externalDomain && e.Domain != wm.newExternalDomain {
|
|
continue
|
|
}
|
|
if e.Generated && !strings.HasSuffix(e.Domain, wm.externalDomain) && !strings.HasSuffix(e.Domain, wm.newExternalDomain) {
|
|
continue
|
|
}
|
|
wm.Instances[e.Aggregate().InstanceID].Domains = append(wm.Instances[e.Aggregate().InstanceID].Domains, e.Domain)
|
|
case *instance.DomainRemovedEvent:
|
|
domains := wm.Instances[e.Aggregate().InstanceID].Domains
|
|
for i, domain := range domains {
|
|
if domain == e.Domain {
|
|
domains[i] = domains[len(domains)-1]
|
|
domains[len(domains)-1] = ""
|
|
wm.Instances[e.Aggregate().InstanceID].Domains = domains[:len(domains)-1]
|
|
break
|
|
}
|
|
}
|
|
case *instance.ProjectSetEvent:
|
|
wm.Instances[e.Aggregate().InstanceID].ProjectID = e.ProjectID
|
|
case *instance.ConsoleSetEvent:
|
|
wm.Instances[e.Aggregate().InstanceID].ConsoleAppID = e.AppID
|
|
case *project.OIDCConfigAddedEvent:
|
|
if wm.Instances[e.Aggregate().InstanceID].ConsoleAppID != e.AppID {
|
|
continue
|
|
}
|
|
wm.Instances[e.Aggregate().InstanceID].RedirectUris = e.RedirectUris
|
|
wm.Instances[e.Aggregate().InstanceID].PostLogoutRedirectUris = e.PostLogoutRedirectUris
|
|
case *project.OIDCConfigChangedEvent:
|
|
if wm.Instances[e.Aggregate().InstanceID].ConsoleAppID != e.AppID {
|
|
continue
|
|
}
|
|
if e.RedirectUris != nil {
|
|
wm.Instances[e.Aggregate().InstanceID].RedirectUris = *e.RedirectUris
|
|
}
|
|
if e.PostLogoutRedirectUris != nil {
|
|
wm.Instances[e.Aggregate().InstanceID].PostLogoutRedirectUris = *e.PostLogoutRedirectUris
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (wm *SystemConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
|
AddQuery().
|
|
AggregateTypes(instance.AggregateType).
|
|
EventTypes(
|
|
instance.InstanceAddedEventType,
|
|
instance.InstanceRemovedEventType,
|
|
instance.InstanceDomainAddedEventType,
|
|
instance.InstanceDomainRemovedEventType,
|
|
instance.ProjectSetEventType,
|
|
instance.ConsoleSetEventType,
|
|
).
|
|
Or().
|
|
AggregateTypes(project.AggregateType).
|
|
EventTypes(
|
|
project.OIDCConfigAddedType,
|
|
project.OIDCConfigChangedType,
|
|
).
|
|
Builder()
|
|
}
|
|
|
|
type SystemConfigChangesValidation struct {
|
|
ProjectID string
|
|
ConsoleAppID string
|
|
Validations []preparation.Validation
|
|
InstanceID string
|
|
}
|
|
|
|
func (wm *SystemConfigWriteModel) NewChangedEvents(commands *Commands) map[string]*SystemConfigChangesValidation {
|
|
var newCustomDomainExists, isInstanceOfCustomDomain bool
|
|
var instanceOfCustomDomain string
|
|
cmds := make(map[string]*SystemConfigChangesValidation)
|
|
for i, inst := range wm.Instances {
|
|
cmds[i] = &SystemConfigChangesValidation{
|
|
InstanceID: i,
|
|
ProjectID: inst.ProjectID,
|
|
ConsoleAppID: inst.ConsoleAppID,
|
|
}
|
|
//check each instance separately for changes (using the generated domain) and check if there's an existing custom domain
|
|
newCustomDomainExists, isInstanceOfCustomDomain = wm.changeConfig(cmds[i], inst, commands)
|
|
if isInstanceOfCustomDomain || newCustomDomainExists {
|
|
instanceOfCustomDomain = i
|
|
}
|
|
}
|
|
//handle the custom domain at last
|
|
if newCustomDomainExists {
|
|
//if the domain itself already exists, then only check if the uris of the console app exist as well
|
|
wm.changeURIs(cmds[instanceOfCustomDomain], wm.Instances[instanceOfCustomDomain], commands, wm.newExternalDomain)
|
|
return cmds
|
|
}
|
|
//otherwise the add instance domain will take care of the uris
|
|
cmds[instanceOfCustomDomain].Validations = append(cmds[instanceOfCustomDomain].Validations, commands.addInstanceDomain(instance.NewAggregate(instanceOfCustomDomain), wm.newExternalDomain, false))
|
|
return cmds
|
|
}
|
|
|
|
func (wm *SystemConfigWriteModel) changeConfig(validation *SystemConfigChangesValidation, inst *systemConfigChangesInstanceModel, commands *Commands) (newCustomDomainExists, isInstanceOfCustomDomain bool) {
|
|
var newGeneratedDomain string
|
|
var newGeneratedDomainExists bool
|
|
for _, domain := range inst.Domains {
|
|
if domain == wm.newExternalDomain {
|
|
newCustomDomainExists = true
|
|
continue
|
|
}
|
|
if domain != wm.newExternalDomain && strings.HasSuffix(domain, wm.newExternalDomain) {
|
|
newGeneratedDomainExists = true
|
|
}
|
|
if !newCustomDomainExists && domain == wm.externalDomain {
|
|
isInstanceOfCustomDomain = true
|
|
}
|
|
if domain != wm.externalDomain && strings.HasSuffix(domain, wm.externalDomain) {
|
|
newGeneratedDomain = strings.TrimSuffix(domain, wm.externalDomain) + wm.newExternalDomain
|
|
}
|
|
}
|
|
if newGeneratedDomainExists {
|
|
//if the domain itself already exists, then only check if the uris of the console app exist as well
|
|
wm.changeURIs(validation, inst, commands, newGeneratedDomain)
|
|
return newCustomDomainExists, isInstanceOfCustomDomain
|
|
}
|
|
//otherwise the add instance domain will take care of the uris
|
|
validation.Validations = append(validation.Validations, commands.addInstanceDomain(instance.NewAggregate(validation.InstanceID), newGeneratedDomain, true))
|
|
return newCustomDomainExists, isInstanceOfCustomDomain
|
|
}
|
|
|
|
func (wm *SystemConfigWriteModel) changeURIs(validation *SystemConfigChangesValidation, inst *systemConfigChangesInstanceModel, commands *Commands, domain string) {
|
|
if commands.checkUpdateConsoleRedirectURIs(domain, inst.RedirectUris, inst.PostLogoutRedirectUris) {
|
|
return
|
|
}
|
|
validation.Validations = append(validation.Validations, commands.prepareUpdateConsoleRedirectURIs(domain))
|
|
}
|