mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 23:37:23 +00:00
feat: custom domain feature (#1618)
* fix: custom domain * fix: custom domain * fix: custom domain * fix: custom domain feature in proto * fix: remove custom domains on feature downgrade * fix test * fix: custom domain feature in proto * ensure tests work Co-authored-by: fabi <fabienne.gerschwiler@gmail.com>
This commit is contained in:
parent
8da733315a
commit
6863aeac59
@ -169,67 +169,6 @@ all fields are updated. If no value is provided the field will be empty afterwar
|
|||||||
|
|
||||||
PUT: /idps/{idp_id}/oidc_config
|
PUT: /idps/{idp_id}/oidc_config
|
||||||
|
|
||||||
|
|
||||||
### GetDefaultFeatures
|
|
||||||
|
|
||||||
> **rpc** GetDefaultFeatures([GetDefaultFeaturesRequest](#getdefaultfeaturesrequest))
|
|
||||||
[GetDefaultFeaturesResponse](#getdefaultfeaturesresponse)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GET: /features
|
|
||||||
|
|
||||||
|
|
||||||
### SetDefaultFeatures
|
|
||||||
|
|
||||||
> **rpc** SetDefaultFeatures([SetDefaultFeaturesRequest](#setdefaultfeaturesrequest))
|
|
||||||
[SetDefaultFeaturesResponse](#setdefaultfeaturesresponse)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PUT: /features
|
|
||||||
|
|
||||||
|
|
||||||
### GetOrgFeatures
|
|
||||||
|
|
||||||
> **rpc** GetOrgFeatures([GetOrgFeaturesRequest](#getorgfeaturesrequest))
|
|
||||||
[GetOrgFeaturesResponse](#getorgfeaturesresponse)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GET: /orgs/{org_id}/features
|
|
||||||
|
|
||||||
|
|
||||||
### SetOrgFeatures
|
|
||||||
|
|
||||||
> **rpc** SetOrgFeatures([SetOrgFeaturesRequest](#setorgfeaturesrequest))
|
|
||||||
[SetOrgFeaturesResponse](#setorgfeaturesresponse)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PUT: /orgs/{org_id}/features
|
|
||||||
|
|
||||||
|
|
||||||
### ResetOrgFeatures
|
|
||||||
|
|
||||||
> **rpc** ResetOrgFeatures([ResetOrgFeaturesRequest](#resetorgfeaturesrequest))
|
|
||||||
[ResetOrgFeaturesResponse](#resetorgfeaturesresponse)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DELETE: /orgs/{org_id}/features
|
|
||||||
|
|
||||||
|
|
||||||
### GetOrgIAMPolicy
|
### GetOrgIAMPolicy
|
||||||
|
|
||||||
> **rpc** GetOrgIAMPolicy([GetOrgIAMPolicyRequest](#getorgiampolicyrequest))
|
> **rpc** GetOrgIAMPolicy([GetOrgIAMPolicyRequest](#getorgiampolicyrequest))
|
||||||
@ -1427,6 +1366,7 @@ if name or domain is already in use, org is not unique
|
|||||||
| login_policy_passwordless | bool | - |
|
| login_policy_passwordless | bool | - |
|
||||||
| password_complexity_policy | bool | - |
|
| password_complexity_policy | bool | - |
|
||||||
| label_policy | bool | - |
|
| label_policy | bool | - |
|
||||||
|
| custom_domain | bool | - |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1457,6 +1397,7 @@ if name or domain is already in use, org is not unique
|
|||||||
| login_policy_passwordless | bool | - |
|
| login_policy_passwordless | bool | - |
|
||||||
| password_complexity_policy | bool | - |
|
| password_complexity_policy | bool | - |
|
||||||
| label_policy | bool | - |
|
| label_policy | bool | - |
|
||||||
|
| custom_domain | bool | - |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ func setDefaultFeaturesRequestToDomain(req *admin_pb.SetDefaultFeaturesRequest)
|
|||||||
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
||||||
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
||||||
LabelPolicy: req.LabelPolicy,
|
LabelPolicy: req.LabelPolicy,
|
||||||
|
CustomDomain: req.CustomDomain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,5 +89,6 @@ func setOrgFeaturesRequestToDomain(req *admin_pb.SetOrgFeaturesRequest) *domain.
|
|||||||
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
|
||||||
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
|
||||||
LabelPolicy: req.LabelPolicy,
|
LabelPolicy: req.LabelPolicy,
|
||||||
|
CustomDomain: req.CustomDomain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ func FeaturesFromModel(features *features_model.FeaturesView) *features_pb.Featu
|
|||||||
LoginPolicyUsernameLogin: features.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: features.LoginPolicyUsernameLogin,
|
||||||
PasswordComplexityPolicy: features.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: features.PasswordComplexityPolicy,
|
||||||
LabelPolicy: features.LabelPolicy,
|
LabelPolicy: features.LabelPolicy,
|
||||||
|
CustomDomain: features.CustomDomain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ type FeaturesWriteModel struct {
|
|||||||
LoginPolicyUsernameLogin bool
|
LoginPolicyUsernameLogin bool
|
||||||
PasswordComplexityPolicy bool
|
PasswordComplexityPolicy bool
|
||||||
LabelPolicy bool
|
LabelPolicy bool
|
||||||
|
CustomDomain bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *FeaturesWriteModel) Reduce() error {
|
func (wm *FeaturesWriteModel) Reduce() error {
|
||||||
@ -66,6 +67,9 @@ func (wm *FeaturesWriteModel) Reduce() error {
|
|||||||
if e.LabelPolicy != nil {
|
if e.LabelPolicy != nil {
|
||||||
wm.LabelPolicy = *e.LabelPolicy
|
wm.LabelPolicy = *e.LabelPolicy
|
||||||
}
|
}
|
||||||
|
if e.CustomDomain != nil {
|
||||||
|
wm.CustomDomain = *e.CustomDomain
|
||||||
|
}
|
||||||
case *features.FeaturesRemovedEvent:
|
case *features.FeaturesRemovedEvent:
|
||||||
wm.State = domain.FeaturesStateRemoved
|
wm.State = domain.FeaturesStateRemoved
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ func (c *Commands) setDefaultFeatures(ctx context.Context, existingFeatures *IAM
|
|||||||
features.LoginPolicyUsernameLogin,
|
features.LoginPolicyUsernameLogin,
|
||||||
features.PasswordComplexityPolicy,
|
features.PasswordComplexityPolicy,
|
||||||
features.LabelPolicy,
|
features.LabelPolicy,
|
||||||
|
features.CustomDomain,
|
||||||
)
|
)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||||
|
@ -62,7 +62,8 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
|||||||
loginPolicyRegistration,
|
loginPolicyRegistration,
|
||||||
loginPolicyUsernameLogin,
|
loginPolicyUsernameLogin,
|
||||||
passwordComplexityPolicy,
|
passwordComplexityPolicy,
|
||||||
labelPolicy bool,
|
labelPolicy,
|
||||||
|
customDomain bool,
|
||||||
) (*iam.FeaturesSetEvent, bool) {
|
) (*iam.FeaturesSetEvent, bool) {
|
||||||
|
|
||||||
changes := make([]features.FeaturesChanges, 0)
|
changes := make([]features.FeaturesChanges, 0)
|
||||||
@ -103,6 +104,9 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
|||||||
if wm.LabelPolicy != labelPolicy {
|
if wm.LabelPolicy != labelPolicy {
|
||||||
changes = append(changes, features.ChangeLabelPolicy(labelPolicy))
|
changes = append(changes, features.ChangeLabelPolicy(labelPolicy))
|
||||||
}
|
}
|
||||||
|
if wm.CustomDomain != customDomain {
|
||||||
|
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
||||||
|
}
|
||||||
|
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -2,13 +2,14 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
|
||||||
|
|
||||||
http_utils "github.com/caos/zitadel/internal/api/http"
|
http_utils "github.com/caos/zitadel/internal/api/http"
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
"github.com/caos/zitadel/internal/repository/org"
|
"github.com/caos/zitadel/internal/repository/org"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -206,6 +207,38 @@ func (c *Commands) addOrgDomain(ctx context.Context, orgAgg *eventstore.Aggregat
|
|||||||
return events, nil
|
return events, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) removeCustomDomains(ctx context.Context, orgID string) ([]eventstore.EventPusher, error) {
|
||||||
|
orgDomains := NewOrgDomainsWriteModel(orgID)
|
||||||
|
err := c.eventstore.FilterToQueryReducer(ctx, orgDomains)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hasDefault := false
|
||||||
|
defaultDomain := domain.NewIAMDomainName(orgDomains.OrgName, c.iamDomain)
|
||||||
|
isPrimary := defaultDomain == orgDomains.PrimaryDomain
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&orgDomains.WriteModel)
|
||||||
|
events := make([]eventstore.EventPusher, 0, len(orgDomains.Domains))
|
||||||
|
for _, orgDomain := range orgDomains.Domains {
|
||||||
|
if orgDomain.State == domain.OrgDomainStateActive {
|
||||||
|
if orgDomain.Domain == defaultDomain {
|
||||||
|
hasDefault = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
events = append(events, org.NewDomainRemovedEvent(ctx, orgAgg, orgDomain.Domain, orgDomain.Verified))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasDefault {
|
||||||
|
return append([]eventstore.EventPusher{
|
||||||
|
org.NewDomainAddedEvent(ctx, orgAgg, defaultDomain),
|
||||||
|
org.NewDomainPrimarySetEvent(ctx, orgAgg, defaultDomain),
|
||||||
|
}, events...), nil
|
||||||
|
}
|
||||||
|
if !isPrimary {
|
||||||
|
return append([]eventstore.EventPusher{org.NewDomainPrimarySetEvent(ctx, orgAgg, defaultDomain)}, events...), nil
|
||||||
|
}
|
||||||
|
return events, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) getOrgDomainWriteModel(ctx context.Context, orgID, domain string) (*OrgDomainWriteModel, error) {
|
func (c *Commands) getOrgDomainWriteModel(ctx context.Context, orgID, domain string) (*OrgDomainWriteModel, error) {
|
||||||
domainWriteModel := NewOrgDomainWriteModel(orgID, domain)
|
domainWriteModel := NewOrgDomainWriteModel(orgID, domain)
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, domainWriteModel)
|
err := c.eventstore.FilterToQueryReducer(ctx, domainWriteModel)
|
||||||
|
@ -95,3 +95,72 @@ func (wm *OrgDomainWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|||||||
org.OrgDomainPrimarySetEventType,
|
org.OrgDomainPrimarySetEventType,
|
||||||
org.OrgDomainRemovedEventType)
|
org.OrgDomainRemovedEventType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrgDomainsWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
Domains []*Domain
|
||||||
|
PrimaryDomain string
|
||||||
|
OrgName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Domain struct {
|
||||||
|
Domain string
|
||||||
|
Verified bool
|
||||||
|
State domain.OrgDomainState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrgDomainsWriteModel(orgID string) *OrgDomainsWriteModel {
|
||||||
|
return &OrgDomainsWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: orgID,
|
||||||
|
ResourceOwner: orgID,
|
||||||
|
},
|
||||||
|
Domains: make([]*Domain, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgDomainsWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.OrgAddedEvent:
|
||||||
|
wm.OrgName = e.Name
|
||||||
|
case *org.OrgChangedEvent:
|
||||||
|
wm.OrgName = e.Name
|
||||||
|
case *org.DomainAddedEvent:
|
||||||
|
wm.Domains = append(wm.Domains, &Domain{Domain: e.Domain, State: domain.OrgDomainStateActive})
|
||||||
|
case *org.DomainVerifiedEvent:
|
||||||
|
for _, d := range wm.Domains {
|
||||||
|
if d.Domain == e.Domain {
|
||||||
|
d.Verified = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *org.DomainPrimarySetEvent:
|
||||||
|
wm.PrimaryDomain = e.Domain
|
||||||
|
case *org.DomainRemovedEvent:
|
||||||
|
for _, d := range wm.Domains {
|
||||||
|
if d.Domain == e.Domain {
|
||||||
|
d.State = domain.OrgDomainStateRemoved
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgDomainsWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID).
|
||||||
|
ResourceOwner(wm.ResourceOwner).
|
||||||
|
EventTypes(
|
||||||
|
org.OrgAddedEventType,
|
||||||
|
org.OrgChangedEventType,
|
||||||
|
org.OrgDomainAddedEventType,
|
||||||
|
org.OrgDomainVerifiedEventType,
|
||||||
|
org.OrgDomainVerificationAddedEventType,
|
||||||
|
org.OrgDomainVerifiedEventType,
|
||||||
|
org.OrgDomainPrimarySetEventType,
|
||||||
|
org.OrgDomainRemovedEventType)
|
||||||
|
}
|
||||||
|
@ -113,6 +113,15 @@ func (c *Commands) ensureOrgSettingsToFeatures(ctx context.Context, orgID string
|
|||||||
events = append(events, removeLabelPolicyEvent)
|
events = append(events, removeLabelPolicyEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !features.CustomDomain {
|
||||||
|
removeCustomDomainsEvents, err := c.removeCustomDomains(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if removeCustomDomainsEvents != nil {
|
||||||
|
events = append(events, removeCustomDomainsEvents...)
|
||||||
|
}
|
||||||
|
}
|
||||||
return events, nil
|
return events, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
|
iamDomain string
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -55,6 +56,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
LoginPolicyUsernameLogin: false,
|
LoginPolicyUsernameLogin: false,
|
||||||
PasswordComplexityPolicy: false,
|
PasswordComplexityPolicy: false,
|
||||||
LabelPolicy: false,
|
LabelPolicy: false,
|
||||||
|
CustomDomain: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -87,6 +89,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
LoginPolicyUsernameLogin: false,
|
LoginPolicyUsernameLogin: false,
|
||||||
PasswordComplexityPolicy: false,
|
PasswordComplexityPolicy: false,
|
||||||
LabelPolicy: false,
|
LabelPolicy: false,
|
||||||
|
CustomDomain: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -136,6 +139,36 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewOrgAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -144,6 +177,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
iamDomain: "iam-domain",
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
@ -159,6 +193,439 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
LoginPolicyUsernameLogin: false,
|
LoginPolicyUsernameLogin: false,
|
||||||
PasswordComplexityPolicy: false,
|
PasswordComplexityPolicy: false,
|
||||||
LabelPolicy: false,
|
LabelPolicy: false,
|
||||||
|
CustomDomain: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "set with default policies, custom domains, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewLoginPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
domain.PasswordlessTypeAllowed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewPasswordComplexityPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
8,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewLabelPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"primary",
|
||||||
|
"secondary",
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewOrgAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test2",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "test1", true),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "test2", false),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
newFeaturesSetEvent(context.Background(), "org1", "Test", domain.FeaturesStateActive, time.Hour),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
uniqueConstraintsFromEventConstraint(org.NewRemoveOrgDomainUniqueConstraint("test1")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
iamDomain: "iam-domain",
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
features: &domain.Features{
|
||||||
|
TierName: "Test",
|
||||||
|
State: domain.FeaturesStateActive,
|
||||||
|
AuditLogRetention: time.Hour,
|
||||||
|
LoginPolicyFactors: false,
|
||||||
|
LoginPolicyIDP: false,
|
||||||
|
LoginPolicyPasswordless: false,
|
||||||
|
LoginPolicyRegistration: false,
|
||||||
|
LoginPolicyUsernameLogin: false,
|
||||||
|
PasswordComplexityPolicy: false,
|
||||||
|
LabelPolicy: false,
|
||||||
|
CustomDomain: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "set with default policies, custom domains, default not primary, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewLoginPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
domain.PasswordlessTypeAllowed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewPasswordComplexityPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
8,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewLabelPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"primary",
|
||||||
|
"secondary",
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewOrgAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test2",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "org1.iam-domain"),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "test1", true),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "test2", false),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
newFeaturesSetEvent(context.Background(), "org1", "Test", domain.FeaturesStateActive, time.Hour),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
uniqueConstraintsFromEventConstraint(org.NewRemoveOrgDomainUniqueConstraint("test1")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
iamDomain: "iam-domain",
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
features: &domain.Features{
|
||||||
|
TierName: "Test",
|
||||||
|
State: domain.FeaturesStateActive,
|
||||||
|
AuditLogRetention: time.Hour,
|
||||||
|
LoginPolicyFactors: false,
|
||||||
|
LoginPolicyIDP: false,
|
||||||
|
LoginPolicyPasswordless: false,
|
||||||
|
LoginPolicyRegistration: false,
|
||||||
|
LoginPolicyUsernameLogin: false,
|
||||||
|
PasswordComplexityPolicy: false,
|
||||||
|
LabelPolicy: false,
|
||||||
|
CustomDomain: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "set with default policies, custom domains, default not existing, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewLoginPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
domain.PasswordlessTypeAllowed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewPasswordComplexityPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
8,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewLabelPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"primary",
|
||||||
|
"secondary",
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewOrgAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"test2",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainRemovedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain", true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "org1.iam-domain"),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "org1.iam-domain"),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "test1", true),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, "test2", false),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
newFeaturesSetEvent(context.Background(), "org1", "Test", domain.FeaturesStateActive, time.Hour),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
uniqueConstraintsFromEventConstraint(org.NewRemoveOrgDomainUniqueConstraint("test1")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
iamDomain: "iam-domain",
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
features: &domain.Features{
|
||||||
|
TierName: "Test",
|
||||||
|
State: domain.FeaturesStateActive,
|
||||||
|
AuditLogRetention: time.Hour,
|
||||||
|
LoginPolicyFactors: false,
|
||||||
|
LoginPolicyIDP: false,
|
||||||
|
LoginPolicyPasswordless: false,
|
||||||
|
LoginPolicyRegistration: false,
|
||||||
|
LoginPolicyUsernameLogin: false,
|
||||||
|
PasswordComplexityPolicy: false,
|
||||||
|
LabelPolicy: false,
|
||||||
|
CustomDomain: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -281,6 +748,36 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewOrgAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -307,6 +804,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
iamDomain: "iam-domain",
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
@ -335,6 +833,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
r := &Commands{
|
r := &Commands{
|
||||||
eventstore: tt.fields.eventstore,
|
eventstore: tt.fields.eventstore,
|
||||||
|
iamDomain: tt.fields.iamDomain,
|
||||||
}
|
}
|
||||||
got, err := r.SetOrgFeatures(tt.args.ctx, tt.args.resourceOwner, tt.args.features)
|
got, err := r.SetOrgFeatures(tt.args.ctx, tt.args.resourceOwner, tt.args.features)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
@ -353,6 +852,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
|
func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
|
iamDomain string
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -448,6 +948,36 @@ func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewOrgAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainVerifiedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewDomainPrimarySetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"org1.iam-domain",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -456,6 +986,7 @@ func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
iamDomain: "iam-domain",
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
@ -472,6 +1003,7 @@ func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
r := &Commands{
|
r := &Commands{
|
||||||
eventstore: tt.fields.eventstore,
|
eventstore: tt.fields.eventstore,
|
||||||
|
iamDomain: tt.fields.iamDomain,
|
||||||
}
|
}
|
||||||
got, err := r.RemoveOrgFeatures(tt.args.ctx, tt.args.resourceOwner)
|
got, err := r.RemoveOrgFeatures(tt.args.ctx, tt.args.resourceOwner)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
|
@ -15,6 +15,7 @@ const (
|
|||||||
FeatureLoginPolicyUsernameLogin = FeatureLoginPolicy + ".username_login"
|
FeatureLoginPolicyUsernameLogin = FeatureLoginPolicy + ".username_login"
|
||||||
FeaturePasswordComplexityPolicy = "password_complexity_policy"
|
FeaturePasswordComplexityPolicy = "password_complexity_policy"
|
||||||
FeatureLabelPolicy = "label_policy"
|
FeatureLabelPolicy = "label_policy"
|
||||||
|
FeatureCustomDomain = "custom_domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Features struct {
|
type Features struct {
|
||||||
@ -34,6 +35,7 @@ type Features struct {
|
|||||||
LoginPolicyUsernameLogin bool
|
LoginPolicyUsernameLogin bool
|
||||||
PasswordComplexityPolicy bool
|
PasswordComplexityPolicy bool
|
||||||
LabelPolicy bool
|
LabelPolicy bool
|
||||||
|
CustomDomain bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type FeaturesState int32
|
type FeaturesState int32
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,11 +27,7 @@ func (o *Org) IsValid() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Org) AddIAMDomain(iamDomain string) {
|
func (o *Org) AddIAMDomain(iamDomain string) {
|
||||||
o.Domains = append(o.Domains, &OrgDomain{Domain: o.nameForDomain(iamDomain), Verified: true, Primary: true})
|
o.Domains = append(o.Domains, &OrgDomain{Domain: NewIAMDomainName(o.Name, iamDomain), Verified: true, Primary: true})
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Org) nameForDomain(iamDomain string) string {
|
|
||||||
return strings.ToLower(strings.ReplaceAll(o.Name, " ", "-") + "." + iamDomain)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrgState int32
|
type OrgState int32
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
http_util "github.com/caos/zitadel/internal/api/http"
|
http_util "github.com/caos/zitadel/internal/api/http"
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
@ -29,6 +31,10 @@ func (domain *OrgDomain) GenerateVerificationCode(codeGenerator crypto.Generator
|
|||||||
return validationCode, nil
|
return validationCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewIAMDomainName(orgName, iamDomain string) string {
|
||||||
|
return strings.ToLower(strings.ReplaceAll(orgName, " ", "-") + "." + iamDomain)
|
||||||
|
}
|
||||||
|
|
||||||
type OrgDomainValidationType int32
|
type OrgDomainValidationType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -25,6 +25,7 @@ type FeaturesView struct {
|
|||||||
LoginPolicyUsernameLogin bool
|
LoginPolicyUsernameLogin bool
|
||||||
PasswordComplexityPolicy bool
|
PasswordComplexityPolicy bool
|
||||||
LabelPolicy bool
|
LabelPolicy bool
|
||||||
|
CustomDomain bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FeaturesView) FeatureList() []string {
|
func (f *FeaturesView) FeatureList() []string {
|
||||||
@ -50,6 +51,9 @@ func (f *FeaturesView) FeatureList() []string {
|
|||||||
if f.LabelPolicy {
|
if f.LabelPolicy {
|
||||||
list = append(list, domain.FeatureLabelPolicy)
|
list = append(list, domain.FeatureLabelPolicy)
|
||||||
}
|
}
|
||||||
|
if f.CustomDomain {
|
||||||
|
list = append(list, domain.FeatureCustomDomain)
|
||||||
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ type FeaturesView struct {
|
|||||||
LoginPolicyUsernameLogin bool `json:"loginPolicyUsernameLogin" gorm:"column:login_policy_username_login"`
|
LoginPolicyUsernameLogin bool `json:"loginPolicyUsernameLogin" gorm:"column:login_policy_username_login"`
|
||||||
PasswordComplexityPolicy bool `json:"passwordComplexityPolicy" gorm:"column:password_complexity_policy"`
|
PasswordComplexityPolicy bool `json:"passwordComplexityPolicy" gorm:"column:password_complexity_policy"`
|
||||||
LabelPolicy bool `json:"labelPolicy" gorm:"column:label_policy"`
|
LabelPolicy bool `json:"labelPolicy" gorm:"column:label_policy"`
|
||||||
|
CustomDomain bool `json:"customDomain" gorm:"column:custom_domain"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
|
func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
|
||||||
@ -59,6 +60,7 @@ func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
|
|||||||
LoginPolicyUsernameLogin: features.LoginPolicyUsernameLogin,
|
LoginPolicyUsernameLogin: features.LoginPolicyUsernameLogin,
|
||||||
PasswordComplexityPolicy: features.PasswordComplexityPolicy,
|
PasswordComplexityPolicy: features.PasswordComplexityPolicy,
|
||||||
LabelPolicy: features.LabelPolicy,
|
LabelPolicy: features.LabelPolicy,
|
||||||
|
CustomDomain: features.CustomDomain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ type FeaturesSetEvent struct {
|
|||||||
LoginPolicyUsernameLogin *bool `json:"loginPolicyUsernameLogin,omitempty"`
|
LoginPolicyUsernameLogin *bool `json:"loginPolicyUsernameLogin,omitempty"`
|
||||||
PasswordComplexityPolicy *bool `json:"passwordComplexityPolicy,omitempty"`
|
PasswordComplexityPolicy *bool `json:"passwordComplexityPolicy,omitempty"`
|
||||||
LabelPolicy *bool `json:"labelPolicy,omitempty"`
|
LabelPolicy *bool `json:"labelPolicy,omitempty"`
|
||||||
|
CustomDomain *bool `json:"customDomain,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *FeaturesSetEvent) Data() interface{} {
|
func (e *FeaturesSetEvent) Data() interface{} {
|
||||||
@ -131,6 +132,12 @@ func ChangeLabelPolicy(labelPolicy bool) func(event *FeaturesSetEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ChangeCustomDomain(customDomain bool) func(event *FeaturesSetEvent) {
|
||||||
|
return func(e *FeaturesSetEvent) {
|
||||||
|
e.CustomDomain = &customDomain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func FeaturesSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
func FeaturesSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
e := &FeaturesSetEvent{
|
e := &FeaturesSetEvent{
|
||||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
4
migrations/cockroach/V1.39__feature_custom_domain.sql
Normal file
4
migrations/cockroach/V1.39__feature_custom_domain.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE adminapi.features ADD COLUMN custom_domain BOOLEAN;
|
||||||
|
ALTER TABLE auth.features ADD COLUMN custom_domain BOOLEAN;
|
||||||
|
ALTER TABLE authz.features ADD COLUMN custom_domain BOOLEAN;
|
||||||
|
ALTER TABLE management.features ADD COLUMN custom_domain BOOLEAN;
|
@ -2188,6 +2188,7 @@ message SetDefaultFeaturesRequest {
|
|||||||
bool login_policy_passwordless = 10;
|
bool login_policy_passwordless = 10;
|
||||||
bool password_complexity_policy = 11;
|
bool password_complexity_policy = 11;
|
||||||
bool label_policy = 12;
|
bool label_policy = 12;
|
||||||
|
bool custom_domain = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SetDefaultFeaturesResponse {
|
message SetDefaultFeaturesResponse {
|
||||||
@ -2217,6 +2218,7 @@ message SetOrgFeaturesRequest {
|
|||||||
bool login_policy_passwordless = 11;
|
bool login_policy_passwordless = 11;
|
||||||
bool password_complexity_policy = 12;
|
bool password_complexity_policy = 12;
|
||||||
bool label_policy = 13;
|
bool label_policy = 13;
|
||||||
|
bool custom_domain = 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SetOrgFeaturesResponse {
|
message SetOrgFeaturesResponse {
|
||||||
|
@ -20,6 +20,7 @@ message Features {
|
|||||||
bool login_policy_passwordless = 9;
|
bool login_policy_passwordless = 9;
|
||||||
bool password_complexity_policy = 10;
|
bool password_complexity_policy = 10;
|
||||||
bool label_policy = 11;
|
bool label_policy = 11;
|
||||||
|
bool custom_domain = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
message FeatureTier {
|
message FeatureTier {
|
||||||
|
@ -597,6 +597,7 @@ service ManagementService {
|
|||||||
|
|
||||||
option (zitadel.v1.auth_option) = {
|
option (zitadel.v1.auth_option) = {
|
||||||
permission: "org.write"
|
permission: "org.write"
|
||||||
|
feature: "custom_domain"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,6 +619,7 @@ service ManagementService {
|
|||||||
|
|
||||||
option (zitadel.v1.auth_option) = {
|
option (zitadel.v1.auth_option) = {
|
||||||
permission: "org.write"
|
permission: "org.write"
|
||||||
|
feature: "custom_domain"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,6 +631,7 @@ service ManagementService {
|
|||||||
|
|
||||||
option (zitadel.v1.auth_option) = {
|
option (zitadel.v1.auth_option) = {
|
||||||
permission: "org.write"
|
permission: "org.write"
|
||||||
|
feature: "custom_domain"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,6 +642,7 @@ service ManagementService {
|
|||||||
|
|
||||||
option (zitadel.v1.auth_option) = {
|
option (zitadel.v1.auth_option) = {
|
||||||
permission: "org.write"
|
permission: "org.write"
|
||||||
|
feature: "custom_domain"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user