mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 08:37:32 +00:00
fix(projection): add idp login policy link (#2590)
* fix(projections): add app * fix(migration): add index for project_id * test: app projection * fix(projections): add idp_user_link * test: idp user link * fix(projection): add idp login policy link * fix: migration versions * fix: migration versions * refactor: rename externalIDP to UserIDPLink * fix: interface * fix: interface methods
This commit is contained in:
148
internal/query/projection/idp_login_policy_link.go
Normal file
148
internal/query/projection/idp_login_policy_link.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package projection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/logging"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/handler"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/handler/crdb"
|
||||||
|
"github.com/caos/zitadel/internal/repository/iam"
|
||||||
|
"github.com/caos/zitadel/internal/repository/org"
|
||||||
|
"github.com/caos/zitadel/internal/repository/policy"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IDPLoginPolicyLinkProjection struct {
|
||||||
|
crdb.StatementHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
IDPLoginPolicyLinkTable = "zitadel.projections.idp_login_policy_links"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewIDPLoginPolicyLinkProjection(ctx context.Context, config crdb.StatementHandlerConfig) *IDPLoginPolicyLinkProjection {
|
||||||
|
p := &IDPLoginPolicyLinkProjection{}
|
||||||
|
config.ProjectionName = IDPLoginPolicyLinkTable
|
||||||
|
config.Reducers = p.reducers()
|
||||||
|
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IDPLoginPolicyLinkProjection) reducers() []handler.AggregateReducer {
|
||||||
|
return []handler.AggregateReducer{
|
||||||
|
{
|
||||||
|
Aggregate: org.AggregateType,
|
||||||
|
EventRedusers: []handler.EventReducer{
|
||||||
|
{
|
||||||
|
Event: org.LoginPolicyIDPProviderAddedEventType,
|
||||||
|
Reduce: p.reduceAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: org.LoginPolicyIDPProviderCascadeRemovedEventType,
|
||||||
|
Reduce: p.reduceCascadeRemoved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: org.LoginPolicyIDPProviderRemovedEventType,
|
||||||
|
Reduce: p.reduceRemoved,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Aggregate: iam.AggregateType,
|
||||||
|
EventRedusers: []handler.EventReducer{
|
||||||
|
{
|
||||||
|
Event: iam.LoginPolicyIDPProviderAddedEventType,
|
||||||
|
Reduce: p.reduceAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: iam.LoginPolicyIDPProviderCascadeRemovedEventType,
|
||||||
|
Reduce: p.reduceCascadeRemoved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: iam.LoginPolicyIDPProviderRemovedEventType,
|
||||||
|
Reduce: p.reduceRemoved,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
IDPLoginPolicyLinkIDPIDCol = "idp_id"
|
||||||
|
IDPLoginPolicyLinkAggregateIDCol = "aggregate_id"
|
||||||
|
IDPLoginPolicyLinkCreationDateCol = "creation_date"
|
||||||
|
IDPLoginPolicyLinkChangeDateCol = "change_date"
|
||||||
|
IDPLoginPolicyLinkSequenceCol = "sequence"
|
||||||
|
IDPLoginPolicyLinkResourceOwnerCol = "resource_owner"
|
||||||
|
IDPLoginPolicyLinkProviderTypeCol = "provider_type"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *IDPLoginPolicyLinkProjection) reduceAdded(event eventstore.EventReader) (*handler.Statement, error) {
|
||||||
|
var (
|
||||||
|
idp policy.IdentityProviderAddedEvent
|
||||||
|
providerType domain.IdentityProviderType
|
||||||
|
)
|
||||||
|
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.IdentityProviderAddedEvent:
|
||||||
|
idp = e.IdentityProviderAddedEvent
|
||||||
|
providerType = domain.IdentityProviderTypeOrg
|
||||||
|
case *iam.IdentityProviderAddedEvent:
|
||||||
|
idp = e.IdentityProviderAddedEvent
|
||||||
|
providerType = domain.IdentityProviderTypeSystem
|
||||||
|
default:
|
||||||
|
logging.LogWithFields("HANDL-oce92", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LoginPolicyIDPProviderAddedEventType, iam.LoginPolicyIDPProviderAddedEventType}).Error("wrong event type")
|
||||||
|
return nil, errors.ThrowInvalidArgument(nil, "HANDL-Nlp55", "reduce.wrong.event.type")
|
||||||
|
}
|
||||||
|
return crdb.NewCreateStatement(&idp,
|
||||||
|
[]handler.Column{
|
||||||
|
handler.NewCol(IDPLoginPolicyLinkIDPIDCol, idp.IDPConfigID),
|
||||||
|
handler.NewCol(IDPLoginPolicyLinkAggregateIDCol, idp.Aggregate().ID),
|
||||||
|
handler.NewCol(IDPLoginPolicyLinkCreationDateCol, idp.CreationDate()),
|
||||||
|
handler.NewCol(IDPLoginPolicyLinkChangeDateCol, idp.CreationDate()),
|
||||||
|
handler.NewCol(IDPLoginPolicyLinkSequenceCol, idp.Sequence()),
|
||||||
|
handler.NewCol(IDPLoginPolicyLinkResourceOwnerCol, idp.Aggregate().ResourceOwner),
|
||||||
|
handler.NewCol(IDPLoginPolicyLinkProviderTypeCol, providerType),
|
||||||
|
},
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IDPLoginPolicyLinkProjection) reduceRemoved(event eventstore.EventReader) (*handler.Statement, error) {
|
||||||
|
var idp policy.IdentityProviderRemovedEvent
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.IdentityProviderRemovedEvent:
|
||||||
|
idp = e.IdentityProviderRemovedEvent
|
||||||
|
case *iam.IdentityProviderRemovedEvent:
|
||||||
|
idp = e.IdentityProviderRemovedEvent
|
||||||
|
default:
|
||||||
|
logging.LogWithFields("HANDL-vAH3I", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LoginPolicyIDPProviderRemovedEventType, iam.LoginPolicyIDPProviderRemovedEventType}).Error("wrong event type")
|
||||||
|
return nil, errors.ThrowInvalidArgument(nil, "HANDL-tUMYY", "reduce.wrong.event.type")
|
||||||
|
}
|
||||||
|
return crdb.NewDeleteStatement(&idp,
|
||||||
|
[]handler.Condition{
|
||||||
|
handler.NewCond(IDPLoginPolicyLinkIDPIDCol, idp.IDPConfigID),
|
||||||
|
handler.NewCond(IDPLoginPolicyLinkAggregateIDCol, idp.Aggregate().ID),
|
||||||
|
},
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IDPLoginPolicyLinkProjection) reduceCascadeRemoved(event eventstore.EventReader) (*handler.Statement, error) {
|
||||||
|
var idp policy.IdentityProviderCascadeRemovedEvent
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.IdentityProviderCascadeRemovedEvent:
|
||||||
|
idp = e.IdentityProviderCascadeRemovedEvent
|
||||||
|
case *iam.IdentityProviderCascadeRemovedEvent:
|
||||||
|
idp = e.IdentityProviderCascadeRemovedEvent
|
||||||
|
default:
|
||||||
|
logging.LogWithFields("HANDL-7lZaf", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LoginPolicyIDPProviderCascadeRemovedEventType, iam.LoginPolicyIDPProviderCascadeRemovedEventType}).Error("wrong event type")
|
||||||
|
return nil, errors.ThrowInvalidArgument(nil, "HANDL-iCKSj", "reduce.wrong.event.type")
|
||||||
|
}
|
||||||
|
return crdb.NewDeleteStatement(&idp,
|
||||||
|
[]handler.Condition{
|
||||||
|
handler.NewCond(IDPLoginPolicyLinkIDPIDCol, idp.IDPConfigID),
|
||||||
|
handler.NewCond(IDPLoginPolicyLinkAggregateIDCol, idp.Aggregate().ID),
|
||||||
|
},
|
||||||
|
), nil
|
||||||
|
}
|
235
internal/query/projection/idp_login_policy_link_test.go
Normal file
235
internal/query/projection/idp_login_policy_link_test.go
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
package projection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/handler"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
"github.com/caos/zitadel/internal/repository/iam"
|
||||||
|
"github.com/caos/zitadel/internal/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
event func(t *testing.T) eventstore.EventReader
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
reduce func(event eventstore.EventReader) (*handler.Statement, error)
|
||||||
|
want wantReduce
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "iam.reduceAdded",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.LoginPolicyIDPProviderAddedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"idpConfigId": "idp-config-id",
|
||||||
|
"idpProviderType": 1
|
||||||
|
}`),
|
||||||
|
), iam.IdentityProviderAddedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&IDPLoginPolicyLinkProjection{}).reduceAdded,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: iam.AggregateType,
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: IDPLoginPolicyLinkTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "INSERT INTO zitadel.projections.idp_login_policy_links (idp_id, aggregate_id, creation_date, change_date, sequence, resource_owner, provider_type) VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-config-id",
|
||||||
|
"agg-id",
|
||||||
|
anyArg{},
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"ro-id",
|
||||||
|
domain.IdentityProviderTypeSystem,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iam.reduceRemoved",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.LoginPolicyIDPProviderRemovedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"idpConfigId": "idp-config-id",
|
||||||
|
"idpProviderType": 1
|
||||||
|
}`),
|
||||||
|
), iam.IdentityProviderRemovedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&IDPLoginPolicyLinkProjection{}).reduceRemoved,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: iam.AggregateType,
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: IDPLoginPolicyLinkTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "DELETE FROM zitadel.projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-config-id",
|
||||||
|
"agg-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iam.reduceCascadeRemoved",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.LoginPolicyIDPProviderCascadeRemovedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"idpConfigId": "idp-config-id",
|
||||||
|
"idpProviderType": 1
|
||||||
|
}`),
|
||||||
|
), iam.IdentityProviderCascadeRemovedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&IDPLoginPolicyLinkProjection{}).reduceCascadeRemoved,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: iam.AggregateType,
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: IDPLoginPolicyLinkTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "DELETE FROM zitadel.projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-config-id",
|
||||||
|
"agg-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "org.reduceAdded",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(org.LoginPolicyIDPProviderAddedEventType),
|
||||||
|
org.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"idpConfigId": "idp-config-id",
|
||||||
|
"idpProviderType": 1
|
||||||
|
}`),
|
||||||
|
), org.IdentityProviderAddedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&IDPLoginPolicyLinkProjection{}).reduceAdded,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: org.AggregateType,
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: IDPLoginPolicyLinkTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "INSERT INTO zitadel.projections.idp_login_policy_links (idp_id, aggregate_id, creation_date, change_date, sequence, resource_owner, provider_type) VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-config-id",
|
||||||
|
"agg-id",
|
||||||
|
anyArg{},
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"ro-id",
|
||||||
|
domain.IdentityProviderTypeOrg,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "org.reduceRemoved",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(org.LoginPolicyIDPProviderRemovedEventType),
|
||||||
|
org.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"idpConfigId": "idp-config-id",
|
||||||
|
"idpProviderType": 1
|
||||||
|
}`),
|
||||||
|
), org.IdentityProviderRemovedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&IDPLoginPolicyLinkProjection{}).reduceRemoved,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: org.AggregateType,
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: IDPLoginPolicyLinkTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "DELETE FROM zitadel.projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-config-id",
|
||||||
|
"agg-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "org.reduceCascadeRemoved",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(org.LoginPolicyIDPProviderCascadeRemovedEventType),
|
||||||
|
org.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"idpConfigId": "idp-config-id",
|
||||||
|
"idpProviderType": 1
|
||||||
|
}`),
|
||||||
|
), org.IdentityProviderCascadeRemovedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&IDPLoginPolicyLinkProjection{}).reduceCascadeRemoved,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: org.AggregateType,
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: IDPLoginPolicyLinkTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "DELETE FROM zitadel.projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-config-id",
|
||||||
|
"agg-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
event := baseEvent(t)
|
||||||
|
got, err := tt.reduce(event)
|
||||||
|
if _, ok := err.(errors.InvalidArgument); !ok {
|
||||||
|
t.Errorf("no wrong event mapping: %v, got: %v", err, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
event = tt.args.event(t)
|
||||||
|
got, err = tt.reduce(event)
|
||||||
|
assertReduce(t, got, err, tt.want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -50,6 +50,7 @@ func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, co
|
|||||||
NewIDPProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["idps"]))
|
NewIDPProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["idps"]))
|
||||||
NewAppProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["apps"]))
|
NewAppProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["apps"]))
|
||||||
NewIDPUserLinkProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["idp_user_links"]))
|
NewIDPUserLinkProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["idp_user_links"]))
|
||||||
|
NewIDPLoginPolicyLinkProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["idp_login_policy_links"]))
|
||||||
NewMailTemplateProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["mail_templates"]))
|
NewMailTemplateProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["mail_templates"]))
|
||||||
NewMessageTextProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["message_texts"]))
|
NewMessageTextProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["message_texts"]))
|
||||||
NewCustomTextProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["custom_texts"]))
|
NewCustomTextProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["custom_texts"]))
|
||||||
|
12
migrations/cockroach/V1.89__idp_login_policy_link.sql
Normal file
12
migrations/cockroach/V1.89__idp_login_policy_link.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE zitadel.projections.idp_login_policy_links(
|
||||||
|
idp_id STRING,
|
||||||
|
aggregate_id STRING,
|
||||||
|
provider_type INT2,
|
||||||
|
|
||||||
|
creation_date TIMESTAMPTZ,
|
||||||
|
change_date TIMESTAMPTZ,
|
||||||
|
sequence INT8,
|
||||||
|
resource_owner STRING,
|
||||||
|
|
||||||
|
PRIMARY KEY (aggregate_id, idp_id)
|
||||||
|
);
|
Reference in New Issue
Block a user