diff --git a/backend/v3/domain/id_provider.go b/backend/v3/domain/id_provider.go
index 4e64b84230..d5f096a80b 100644
--- a/backend/v3/domain/id_provider.go
+++ b/backend/v3/domain/id_provider.go
@@ -6,6 +6,7 @@ import (
"github.com/zitadel/zitadel/backend/v3/storage/database"
"github.com/zitadel/zitadel/internal/crypto"
+ "github.com/zitadel/zitadel/internal/domain"
)
//go:generate enumer -type IDPType -transform lower -trimprefix IDPType
@@ -236,6 +237,35 @@ type IDPLDAP struct {
LDAP
}
+type Apple struct {
+ ClientID string `json:"clientId"`
+ TeamID string `json:"teamId"`
+ KeyID string `json:"keyId"`
+ PrivateKey *crypto.CryptoValue `json:"privateKey"`
+ Scopes []string `json:"scopes,omitempty"`
+}
+
+type IDPApple struct {
+ *IdentityProvider
+ Apple
+}
+
+type SAML struct {
+ Metadata []byte `json:"metadata,omitempty"`
+ Key *crypto.CryptoValue `json:"key,omitempty"`
+ Certificate []byte `json:"certificate,omitempty"`
+ Binding string `json:"binding,omitempty"`
+ WithSignedRequest bool `json:"withSignedRequest,omitempty"`
+ NameIDFormat *domain.SAMLNameIDFormat `json:"nameIDFormat,omitempty"`
+ TransientMappingAttributeName string `json:"transientMappingAttributeName,omitempty"`
+ FederatedLogoutEnabled bool `json:"federatedLogoutEnabled,omitempty"`
+}
+
+type IDPSAML struct {
+ *IdentityProvider
+ SAML
+}
+
// IDPIdentifierCondition is used to help specify a single identity_provider,
// it will either be used as the identity_provider ID or identity_provider name,
// as identity_provider can be identified either using (instanceID + OrgID + ID) OR (instanceID + OrgID + name)
@@ -316,4 +346,6 @@ type IDProviderRepository interface {
GetGitlab(ctx context.Context, id IDPIdentifierCondition, instanceID string, orgID *string) (*IDPGitlab, error)
GetGitlabSelfHosting(ctx context.Context, id IDPIdentifierCondition, instanceID string, orgID *string) (*IDPGitlabSelfHosting, error)
GetLDAP(ctx context.Context, id IDPIdentifierCondition, instanceID string, orgID *string) (*IDPLDAP, error)
+ GetApple(ctx context.Context, id IDPIdentifierCondition, instanceID string, orgID *string) (*IDPApple, error)
+ GetSAML(ctx context.Context, id IDPIdentifierCondition, instanceID string, orgID *string) (*IDPSAML, error)
}
diff --git a/backend/v3/storage/database/events_testing/id_provider_org_test.go b/backend/v3/storage/database/events_testing/id_provider_org_test.go
index 8c9951be73..384141cbc8 100644
--- a/backend/v3/storage/database/events_testing/id_provider_org_test.go
+++ b/backend/v3/storage/database/events_testing/id_provider_org_test.go
@@ -14,6 +14,7 @@ import (
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
+ zitadel_internal_domain "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/integration"
"github.com/zitadel/zitadel/pkg/grpc/idp"
idp_grpc "github.com/zitadel/zitadel/pkg/grpc/idp"
@@ -2140,4 +2141,297 @@ func TestServer_TestIDProviderOrgReduces(t *testing.T) {
assert.Equal(t, "new_profileAttribute", updateLdap.ProfileAttribute)
}, retryDuration, tick)
})
+
+ t.Run("test instance apple added reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+
+ // add apple
+ beforeCreate := time.Now()
+ // addApple, err := AdminClient.AddAppleProvider(CTX, &admin.AddAppleProviderRequest{
+ addApple, err := MgmtClient.AddAppleProvider(CTX, &management.AddAppleProviderRequest{
+ Name: name,
+ ClientId: "clientID",
+ TeamId: "teamIDteam",
+ KeyId: "keyIDKeyId",
+ PrivateKey: []byte("privateKey"),
+ Scopes: []string{"scope"},
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ apple, err := idpRepo.GetApple(CTX, idpRepo.IDCondition(addApple.Id), instanceID, &orgID)
+ require.NoError(t, err)
+
+ // event instance.idp.apple.added
+ // idp
+ assert.Equal(t, instanceID, apple.InstanceID)
+ assert.Equal(t, orgID, *apple.OrgID)
+ assert.Equal(t, addApple.Id, apple.ID)
+ assert.Equal(t, name, apple.Name)
+ assert.Equal(t, domain.IDPTypeApple.String(), apple.Type)
+ assert.Equal(t, false, apple.AllowLinking)
+ assert.Equal(t, false, apple.AllowCreation)
+ assert.Equal(t, false, apple.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionEmail.String(), apple.AllowAutoLinking)
+ assert.WithinRange(t, apple.CreatedAt, beforeCreate, afterCreate)
+ assert.WithinRange(t, apple.UpdatedAt, beforeCreate, afterCreate)
+
+ // apple
+ assert.Equal(t, "clientID", apple.ClientID)
+ assert.Equal(t, "teamIDteam", apple.TeamID)
+ assert.Equal(t, "keyIDKeyId", apple.KeyID)
+ assert.NotNil(t, apple.PrivateKey)
+ assert.Equal(t, []string{"scope"}, apple.Scopes)
+ }, retryDuration, tick)
+ })
+
+ t.Run("test instance apple changed reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+
+ // add apple
+ addApple, err := MgmtClient.AddAppleProvider(CTX, &management.AddAppleProviderRequest{
+ Name: name,
+ ClientId: "clientID",
+ TeamId: "teamIDteam",
+ KeyId: "keyIDKeyId",
+ PrivateKey: []byte("privateKey"),
+ Scopes: []string{"scope"},
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ var apple *domain.IDPApple
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ apple, err = idpRepo.GetApple(CTX, idpRepo.IDCondition(addApple.Id), instanceID, &orgID)
+ require.NoError(t, err)
+ assert.Equal(t, addApple.Id, apple.ID)
+ }, retryDuration, tick)
+
+ name = "new_" + name
+ // change apple
+ beforeCreate := time.Now()
+ // _, err = AdminClient.UpdateAppleProvider(CTX, &admin.UpdateAppleProviderRequest{
+ _, err = MgmtClient.UpdateAppleProvider(CTX, &management.UpdateAppleProviderRequest{
+ Id: addApple.Id,
+ Name: name,
+ ClientId: "new_clientID",
+ TeamId: "new_teamID",
+ KeyId: "new_kKeyId",
+ PrivateKey: []byte("new_privateKey"),
+ Scopes: []string{"new_scope"},
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: true,
+ IsCreationAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ // check values for apple
+ retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ updateApple, err := idpRepo.GetApple(CTX, idpRepo.IDCondition(addApple.Id), instanceID, &orgID)
+ require.NoError(t, err)
+
+ // event nstance.idp.apple.changed
+ // idp
+ assert.Equal(t, instanceID, updateApple.InstanceID)
+ assert.Equal(t, orgID, *updateApple.OrgID)
+ assert.Equal(t, addApple.Id, updateApple.ID)
+ assert.Equal(t, name, updateApple.Name)
+ assert.Equal(t, domain.IDPTypeApple.String(), updateApple.Type)
+ assert.Equal(t, true, updateApple.AllowLinking)
+ assert.Equal(t, true, updateApple.AllowCreation)
+ assert.Equal(t, true, updateApple.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionUserName.String(), updateApple.AllowAutoLinking)
+ assert.WithinRange(t, updateApple.UpdatedAt, beforeCreate, afterCreate)
+
+ // apple
+ assert.Equal(t, "new_clientID", updateApple.ClientID)
+ assert.Equal(t, "new_teamID", updateApple.TeamID)
+ assert.Equal(t, "new_kKeyId", updateApple.KeyID)
+ assert.NotEqual(t, apple.PrivateKey, updateApple.PrivateKey)
+ assert.Equal(t, []string{"new_scope"}, updateApple.Scopes)
+ }, retryDuration, tick)
+ })
+
+ t.Run("test instance saml added reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+ federatedLogoutEnabled := false
+
+ // add saml
+ beforeCreate := time.Now()
+ addSAML, err := MgmtClient.AddSAMLProvider(CTX, &management.AddSAMLProviderRequest{
+ Name: name,
+ Metadata: &management.AddSAMLProviderRequest_MetadataXml{
+ MetadataXml: validSAMLMetadata1,
+ },
+ Binding: idp.SAMLBinding_SAML_BINDING_POST,
+ WithSignedRequest: false,
+ TransientMappingAttributeName: &name,
+ FederatedLogoutEnabled: &federatedLogoutEnabled,
+ NameIdFormat: idp.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_TRANSIENT.Enum(),
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ saml, err := idpRepo.GetSAML(CTX, idpRepo.IDCondition(addSAML.Id), instanceID, &orgID)
+ require.NoError(t, err)
+
+ // event instance.idp.saml.added
+ // idp
+ assert.Equal(t, instanceID, saml.InstanceID)
+ assert.Equal(t, orgID, *saml.OrgID)
+ assert.Equal(t, addSAML.Id, saml.ID)
+ assert.Equal(t, name, saml.Name)
+ assert.Equal(t, domain.IDPTypeSAML.String(), saml.Type)
+ assert.Equal(t, false, saml.AllowLinking)
+ assert.Equal(t, false, saml.AllowCreation)
+ assert.Equal(t, false, saml.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionEmail.String(), saml.AllowAutoLinking)
+ assert.WithinRange(t, saml.CreatedAt, beforeCreate, afterCreate)
+ assert.WithinRange(t, saml.UpdatedAt, beforeCreate, afterCreate)
+
+ // saml
+ assert.Equal(t, validSAMLMetadata1, saml.Metadata)
+ assert.NotNil(t, saml.Key)
+ assert.NotNil(t, saml.Certificate)
+ assert.NotNil(t, saml.Binding)
+ assert.Equal(t, false, saml.WithSignedRequest)
+ assert.Equal(t, zitadel_internal_domain.SAMLNameIDFormatTransient, *saml.NameIDFormat)
+ assert.Equal(t, name, saml.TransientMappingAttributeName)
+ assert.Equal(t, false, saml.FederatedLogoutEnabled)
+ }, retryDuration, tick)
+ })
+
+ t.Run("test instance saml changed reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+ federatedLogoutEnabled := false
+
+ // add saml
+ addSAML, err := MgmtClient.AddSAMLProvider(CTX, &management.AddSAMLProviderRequest{
+ Name: name,
+ // Metadata: &admin.AddSAMLProviderRequest_MetadataXml{
+ Metadata: &management.AddSAMLProviderRequest_MetadataXml{
+ MetadataXml: validSAMLMetadata1,
+ },
+ Binding: idp.SAMLBinding_SAML_BINDING_POST,
+ WithSignedRequest: false,
+ TransientMappingAttributeName: &name,
+ FederatedLogoutEnabled: &federatedLogoutEnabled,
+ NameIdFormat: idp.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_TRANSIENT.Enum(),
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ var saml *domain.IDPSAML
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ saml, err = idpRepo.GetSAML(CTX, idpRepo.IDCondition(addSAML.Id), instanceID, &orgID)
+ require.NoError(t, err)
+ assert.Equal(t, addSAML.Id, saml.ID)
+ }, retryDuration, tick)
+
+ name = "new_" + name
+ federatedLogoutEnabled = true
+ // change saml
+ beforeCreate := time.Now()
+ _, err = MgmtClient.UpdateSAMLProvider(CTX, &management.UpdateSAMLProviderRequest{
+ Id: addSAML.Id,
+ Name: name,
+ // Metadata: &admin.UpdateSAMLProviderRequest_MetadataXml{
+ Metadata: &management.UpdateSAMLProviderRequest_MetadataXml{
+ MetadataXml: validSAMLMetadata2,
+ },
+ Binding: idp.SAMLBinding_SAML_BINDING_ARTIFACT,
+ WithSignedRequest: true,
+ TransientMappingAttributeName: &name,
+ FederatedLogoutEnabled: &federatedLogoutEnabled,
+ NameIdFormat: idp.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_EMAIL_ADDRESS.Enum(),
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: true,
+ IsCreationAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ // check values for apple
+ retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ updateSAML, err := idpRepo.GetSAML(CTX, idpRepo.IDCondition(addSAML.Id), instanceID, &orgID)
+ require.NoError(t, err)
+
+ // event instance.idp.saml.changed
+ // idp
+ assert.Equal(t, instanceID, updateSAML.InstanceID)
+ assert.Equal(t, orgID, *updateSAML.OrgID)
+ assert.Equal(t, addSAML.Id, updateSAML.ID)
+ assert.Equal(t, name, updateSAML.Name)
+ assert.Equal(t, domain.IDPTypeSAML.String(), updateSAML.Type)
+ assert.Equal(t, true, updateSAML.AllowLinking)
+ assert.Equal(t, true, updateSAML.AllowCreation)
+ assert.Equal(t, true, updateSAML.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionUserName.String(), updateSAML.AllowAutoLinking)
+ assert.WithinRange(t, updateSAML.UpdatedAt, beforeCreate, afterCreate)
+
+ // saml
+ assert.Equal(t, validSAMLMetadata2, updateSAML.Metadata)
+ assert.NotNil(t, updateSAML.Key)
+ // assert.NotEqual(t, saml.Key, updateSAML.Key) // https://github.com/zitadel/zitadel/issues/10414
+ assert.NotNil(t, updateSAML.Certificate)
+ // assert.NotEqual(t, saml.Certificate, updateSAML.Certificate) // https://github.com/zitadel/zitadel/issues/10414
+ assert.NotNil(t, updateSAML.Binding)
+ assert.NotEqual(t, saml.Binding, updateSAML.Binding)
+ assert.Equal(t, true, updateSAML.WithSignedRequest)
+ assert.Equal(t, zitadel_internal_domain.SAMLNameIDFormatEmailAddress, *updateSAML.NameIDFormat)
+ assert.Equal(t, name, updateSAML.TransientMappingAttributeName)
+ assert.Equal(t, true, updateSAML.FederatedLogoutEnabled)
+ }, retryDuration, tick)
+ })
}
diff --git a/backend/v3/storage/database/events_testing/id_provider_test.go b/backend/v3/storage/database/events_testing/id_provider_test.go
index 150d0439db..ff44d80b1c 100644
--- a/backend/v3/storage/database/events_testing/id_provider_test.go
+++ b/backend/v3/storage/database/events_testing/id_provider_test.go
@@ -13,6 +13,7 @@ import (
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
+ zitadel_internal_domain "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/integration"
"github.com/zitadel/zitadel/pkg/grpc/admin"
"github.com/zitadel/zitadel/pkg/grpc/idp"
@@ -20,6 +21,123 @@ import (
durationpb "google.golang.org/protobuf/types/known/durationpb"
)
+var validSAMLMetadata1 = []byte(`
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+
+
+
+
+ urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic
+
+
+
+
+
+
+
+
+ urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+
+
+ http://localhost:8080/saml/v2/metadata IDP signing
+
+ MIIFIjCCAwqgAwIBAgICA7QwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjUwMloXDTI1MTEyNzE2MjUwMlowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIHJlc3BvbnNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2lUgaI6AS/9xvM9DNSWK6Ho64LpK8UIioM26QfvAfeQ/I2pgX6SwWxEbd7qv+PkJzaFTjrXSlwOmWsJYma+UsdyFClaGFRyCgY8SWxPceandC8a+hQIDS/irLd9XF33RWp0b/09HjQl+n0HZ4teUFDUd2U1mUf3XCpn0+Ho316bmi6xSW6zaMy5RsbUl01hgWj2fgapAsGAHSBphwCE3Dz/9I/UfHWQw1k2/UTgjc9uIujcza6WgOxfsKluXYIOxwNKTfmzzOJMUwXz6GRgB2jhQI29MuKOZOITA7pXq5kZKf0lSRU8zKFTMJaK4zAHQ6f877Drr8XdAHemuXGZ2JdH/Dbdwarzy3YBMCWsAYlpeEvaVAdiSpyR7fAZktNuHd39Zg00Vlj2wdc44Vk5yVssW7pv5qnVZ7JTrXX2uBYFecLAXmplQ2ph1VdSXZLEDGgjiNA2T/fBj7G4/VjsuCBZFm1I0KCJp3HWEJx5dwwhSVc5wOJEzl7fMuPYMKWH/RM6P/7LnO1ulpdmiKPa4gHzdg3hDZn42NKcVt3UYf0phtxpWMrZp/DUEeizhckrC4ed6cfGtS3CUtJEqoycrCROJ5Hy+ONHl5Aqxt+JoPU+t/XATuctfPxQVcDr0itHzo2cjh/AVTU+IC7C0oQHSS9CC8Fp58UqbtYwFtSAd7ecCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQAp+IGZScVIbRdCq5HPjlYBPOY7UbL8ZXnlMW/HLELV9GndnULuFhnuQTIdA5dquCsk8RI1fKsScEV1rqWvHZeSo5nVbvUaPJctoD/4GACqE6F8axs1AgSOvpJMyuycjSzSh6gDM1z37Fdqc/2IRqgi7SKdDsfJpi8XW8LtErpp4kyE1rEXopsXG2fe1UH25bZpXraUqYvp61rwVUCazAtV/U7ARG5AnT0mPqzUriIPrfL+v/+2ntV/BSc8/uCqYnHbwpIwjPURCaxo1Pmm6EEkm+V/Ss4ieNwwkD2bLLLST1LoVMim7Ebfy53PEKpsznKsGlVSu0YYKUsStWQVpwhKQw0bQLCJHdpvZtZSDgS9RbSMZz+aY/fpoNx6wDvmMgtdrb3pVXZ8vPKdq9YDrGfFqP60QdZ3CuSHXCM/zX4742GgImJ4KYAcTuF1+BkGf5JLAJOUZBkfCQ/kBT5wr8+EotLxASOC6717whLBYMEG6N8osEk+LDqoJRTLqkzirJsyOHWChKK47yGkdS3HBIZfo91QrJwKpfATYziBjEnqipkTu+6jFylBIkxKTPye4b3vgcodZP8LSNVXAsMGTPNPJxzPWQ37ba4zMnYZ5iUerlaox/SNsn68DT6RajIb1A1JDq+HNFc3hQP2bzk2y5pCax8zo5swjdklnm4clfB2Lw==
+
+
+
+
+
+
+ urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+ urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic
+
+
+
+
+
+
+
+
+ http://localhost:8080/saml/v2/metadata IDP signing
+
+ MIIFIjCCAwqgAwIBAgICA7QwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjUwMloXDTI1MTEyNzE2MjUwMlowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIHJlc3BvbnNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2lUgaI6AS/9xvM9DNSWK6Ho64LpK8UIioM26QfvAfeQ/I2pgX6SwWxEbd7qv+PkJzaFTjrXSlwOmWsJYma+UsdyFClaGFRyCgY8SWxPceandC8a+hQIDS/irLd9XF33RWp0b/09HjQl+n0HZ4teUFDUd2U1mUf3XCpn0+Ho316bmi6xSW6zaMy5RsbUl01hgWj2fgapAsGAHSBphwCE3Dz/9I/UfHWQw1k2/UTgjc9uIujcza6WgOxfsKluXYIOxwNKTfmzzOJMUwXz6GRgB2jhQI29MuKOZOITA7pXq5kZKf0lSRU8zKFTMJaK4zAHQ6f877Drr8XdAHemuXGZ2JdH/Dbdwarzy3YBMCWsAYlpeEvaVAdiSpyR7fAZktNuHd39Zg00Vlj2wdc44Vk5yVssW7pv5qnVZ7JTrXX2uBYFecLAXmplQ2ph1VdSXZLEDGgjiNA2T/fBj7G4/VjsuCBZFm1I0KCJp3HWEJx5dwwhSVc5wOJEzl7fMuPYMKWH/RM6P/7LnO1ulpdmiKPa4gHzdg3hDZn42NKcVt3UYf0phtxpWMrZp/DUEeizhckrC4ed6cfGtS3CUtJEqoycrCROJ5Hy+ONHl5Aqxt+JoPU+t/XATuctfPxQVcDr0itHzo2cjh/AVTU+IC7C0oQHSS9CC8Fp58UqbtYwFtSAd7ecCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQAp+IGZScVIbRdCq5HPjlYBPOY7UbL8ZXnlMW/HLELV9GndnULuFhnuQTIdA5dquCsk8RI1fKsScEV1rqWvHZeSo5nVbvUaPJctoD/4GACqE6F8axs1AgSOvpJMyuycjSzSh6gDM1z37Fdqc/2IRqgi7SKdDsfJpi8XW8LtErpp4kyE1rEXopsXG2fe1UH25bZpXraUqYvp61rwVUCazAtV/U7ARG5AnT0mPqzUriIPrfL+v/+2ntV/BSc8/uCqYnHbwpIwjPURCaxo1Pmm6EEkm+V/Ss4ieNwwkD2bLLLST1LoVMim7Ebfy53PEKpsznKsGlVSu0YYKUsStWQVpwhKQw0bQLCJHdpvZtZSDgS9RbSMZz+aY/fpoNx6wDvmMgtdrb3pVXZ8vPKdq9YDrGfFqP60QdZ3CuSHXCM/zX4742GgImJ4KYAcTuF1+BkGf5JLAJOUZBkfCQ/kBT5wr8+EotLxASOC6717whLBYMEG6N8osEk+LDqoJRTLqkzirJsyOHWChKK47yGkdS3HBIZfo91QrJwKpfATYziBjEnqipkTu+6jFylBIkxKTPye4b3vgcodZP8LSNVXAsMGTPNPJxzPWQ37ba4zMnYZ5iUerlaox/SNsn68DT6RajIb1A1JDq+HNFc3hQP2bzk2y5pCax8zo5swjdklnm4clfB2Lw==
+
+
+
+
+`)
+
+var validSAMLMetadata2 = []byte(`
+
+
+
+
+
+ MIID7TCCAtWgAwIBAgIJANn3qP9lF7M3MA0GCSqGSIb3DQEBCwUAMIGMMQswCQYDVQQGEwJVQTEXMBUGA1UE
+ CAwOS2hhcmtpdiBSZWdpb24xEDAOBgNVBAcMB0toYXJrb3YxDzANBgNVBAoMBk9yYWNsZTEYMBYGA1UEAwwPc3RzeWJvdi12bTEudWEzMScw
+ JQYJKoZIhvcNAQkBFhhzZXJnaWkudHN5Ym92QG9yYWNsZS5jb20wHhcNMTUxMjI1MTIyMjU5WhcNMjUxMjI0MTIyMjU5WjCBjDELMAkGA1UE
+ BhMCVUExFzAVBgNVBAgMDktoYXJraXYgUmVnaW9uMRAwDgYDVQQHDAdLaGFya292MQ8wDQYDVQQKDAZPcmFjbGUxGDAWBgNVBAMMD3N0c3lib
+ 3Ytdm0xLnVhMzEnMCUGCSqGSIb3DQEJARYYc2VyZ2lpLnRzeWJvdkBvcmFjbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCA
+ QEAw4OFwuUNjn6xxb/OuAnmQA6mCWPY2hKMoOz0cAajUHjNZZMwGnuEeUyPtEcULfz2MYo1yKQLxVj3pY0HTIQAzpY8o+xCqJFQmdMiakb
+ PFHlh4z/qqiS5jHng6JCeUpCIxeiTG9JXVwF1ErBEZbwZYjVxa6S+0grVkS3YxuH4uTyqxskuGnHK/AviTHLBrLfSrbFKYuQUrXyy6X22wpzo
+ bQ3Z+4bhEE8SXQtVbQdy7K0MKWYopNhX05SMTv7yMfUGp8EkGNyJ5Km8AuQt6ZCbVao6cHL2hSujQiN6aMjKbdzHeA1QEicppnnoG/Zefyi/
+ okWdlLAaLjcpYrjUSWQJZQIDAQABo1AwTjAdBgNVHQ4EFgQUIKa0zeXmAJsCuNhJjhU0o7KiQgYwHwYDVR0jBBgwFoAUIKa0zeXmAJsCuNhJj
+ hU0o7KiQgYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAJawU5WRXqkW4emm+djpJAxZ0076qPgEsaaog6ng4MLAlU7RmfIY/
+ l0VhXQegvhIBfG4OfduuzGaqd9y4IsQZFJ0yuotl96iEVcqg7hJ1LEY6UT6u6dZyGj1a9I6IlwJm/9CXFZHuVqGJkMfQZ4gaunE4c5gjbQA5/
+ +PEJwPorKn48w8bojymV8hriqzrmaP8eQNuZUJsJdnKENOE5/asGyj+R2YfP6bmlOX3q0ozLcyJbXeZ6IvDFdRiDH5wO4JqW/ujvdvC553y
+ CO3xxsorB4xCupuHu/c7vkzNpaKjYdmGRkqhEqBcCqYSxdwIFc1xhOwYPWKJzgn7pGQsT7yNJg==
+
+
+
+
+
+
+ MIID7TCCAtWgAwIBAgIJANn3qP9lF7M3MA0GCSqGSIb3DQEBCwUAMIGMMQswCQYDVQQGEwJVQTEXMBUGA1
+ UECAwOS2hhcmtpdiBSZWdpb24xEDAOBgNVBAcMB0toYXJrb3YxDzANBgNVBAoMBk9yYWNsZTEYMBYGA1UEAwwPc3RzeWJvdi12bTEud
+ WEzMScwJQYJKoZIhvcNAQkBFhhzZXJnaWkudHN5Ym92QG9yYWNsZS5jb20wHhcNMTUxMjI1MTIyMjU5WhcNMjUxMjI0MTIyMjU5WjCB
+ jDELMAkGA1UEBhMCVUExFzAVBgNVBAgMDktoYXJraXYgUmVnaW9uMRAwDgYDVQQHDAdLaGFya292MQ8wDQYDVQQKDAZPcmFjbGUxGDA
+ WBgNVBAMMD3N0c3lib3Ytdm0xLnVhMzEnMCUGCSqGSIb3DQEJARYYc2VyZ2lpLnRzeWJvdkBvcmFjbGUuY29tMIIBIjANBgkqhkiG9w0B
+ AQEFAAOCAQ8AMIIBCgKCAQEAw4OFwuUNjn6xxb/OuAnmQA6mCWPY2hKMoOz0cAajUHjNZZMwGnuEeUyPtEcULfz2MYo1yKQLxVj3pY0HT
+ IQAzpY8o+xCqJFQmdMiakbPFHlh4z/qqiS5jHng6JCeUpCIxeiTG9JXVwF1ErBEZbwZYjVxa6S+0grVkS3YxuH4uTyqxskuGnHK/
+ AviTHLBrLfSrbFKYuQUrXyy6X22wpzobQ3Z+4bhEE8SXQtVbQdy7K0MKWYopNhX05SMTv7yMfUGp8EkGNyJ5Km8AuQt6ZCbVao6cHL2h
+ SujQiN6aMjKbdzHeA1QEicppnnoG/Zefyi/okWdlLAaLjcpYrjUSWQJZQIDAQABo1AwTjAdBgNVHQ4EFgQUIKa0zeXmAJsCuNhJjhU0o
+ 7KiQgYwHwYDVR0jBBgwFoAUIKa0zeXmAJsCuNhJjhU0o7KiQgYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAJawU5WRXq
+ kW4emm+djpJAxZ0076qPgEsaaog6ng4MLAlU7RmfIY/l0VhXQegvhIBfG4OfduuzGaqd9y4IsQZFJ0yuotl96iEVcqg7hJ1LEY6UT6u6d
+ ZyGj1a9I6IlwJm/9CXFZHuVqGJkMfQZ4gaunE4c5gjbQA5/+PEJwPorKn48w8bojymV8hriqzrmaP8eQNuZUJsJdnKENOE5/
+ asGyj+R2YfP6bmlOX3q0ozLcyJbXeZ6IvDFdRiDH5wO4JqW/ujvdvC553yCO3xxsorB4xCupuHu/c7vkzNpaKjYdmGRkqhEqBcCqYSxd
+ wIFc1xhOwYPWKJzgn7pGQsT7yNJg==
+
+
+
+
+ urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+
+
+
+ Administrator
+ name@emailprovider.com
+
+`)
+
func TestServer_TestIDProviderReduces(t *testing.T) {
instanceID := Instance.ID()
@@ -2102,4 +2220,293 @@ func TestServer_TestIDProviderReduces(t *testing.T) {
assert.Equal(t, "new_profileAttribute", updateLdap.ProfileAttribute)
}, retryDuration, tick)
})
+
+ t.Run("test instance apple added reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+
+ // add apple
+ beforeCreate := time.Now()
+ addApple, err := AdminClient.AddAppleProvider(CTX, &admin.AddAppleProviderRequest{
+ Name: name,
+ ClientId: "clientID",
+ TeamId: "teamIDteam",
+ KeyId: "keyIDKeyId",
+ PrivateKey: []byte("privateKey"),
+ Scopes: []string{"scope"},
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ apple, err := idpRepo.GetApple(CTX, idpRepo.IDCondition(addApple.Id), instanceID, nil)
+ require.NoError(t, err)
+
+ // event instance.idp.apple.added
+ // idp
+ assert.Equal(t, instanceID, apple.InstanceID)
+ assert.Nil(t, apple.OrgID)
+ assert.Equal(t, addApple.Id, apple.ID)
+ assert.Equal(t, name, apple.Name)
+ assert.Equal(t, domain.IDPTypeApple.String(), apple.Type)
+ assert.Equal(t, false, apple.AllowLinking)
+ assert.Equal(t, false, apple.AllowCreation)
+ assert.Equal(t, false, apple.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionEmail.String(), apple.AllowAutoLinking)
+ assert.WithinRange(t, apple.CreatedAt, beforeCreate, afterCreate)
+ assert.WithinRange(t, apple.UpdatedAt, beforeCreate, afterCreate)
+
+ // apple
+ assert.Equal(t, "clientID", apple.ClientID)
+ assert.Equal(t, "teamIDteam", apple.TeamID)
+ assert.Equal(t, "keyIDKeyId", apple.KeyID)
+ assert.NotNil(t, apple.PrivateKey)
+ assert.Equal(t, []string{"scope"}, apple.Scopes)
+ }, retryDuration, tick)
+ })
+
+ t.Run("test instance apple changed reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+
+ // add apple
+ addApple, err := AdminClient.AddAppleProvider(CTX, &admin.AddAppleProviderRequest{
+ Name: name,
+ ClientId: "clientID",
+ TeamId: "teamIDteam",
+ KeyId: "keyIDKeyId",
+ PrivateKey: []byte("privateKey"),
+ Scopes: []string{"scope"},
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ var apple *domain.IDPApple
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ apple, err = idpRepo.GetApple(CTX, idpRepo.IDCondition(addApple.Id), instanceID, nil)
+ require.NoError(t, err)
+ assert.Equal(t, addApple.Id, apple.ID)
+ }, retryDuration, tick)
+
+ name = "new_" + name
+ // change apple
+ beforeCreate := time.Now()
+ _, err = AdminClient.UpdateAppleProvider(CTX, &admin.UpdateAppleProviderRequest{
+ Id: addApple.Id,
+ Name: name,
+ ClientId: "new_clientID",
+ TeamId: "new_teamID",
+ KeyId: "new_kKeyId",
+ PrivateKey: []byte("new_privateKey"),
+ Scopes: []string{"new_scope"},
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: true,
+ IsCreationAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ // check values for apple
+ retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ updateApple, err := idpRepo.GetApple(CTX, idpRepo.IDCondition(addApple.Id), instanceID, nil)
+ require.NoError(t, err)
+
+ // event nstance.idp.apple.changed
+ // idp
+ assert.Equal(t, instanceID, updateApple.InstanceID)
+ assert.Nil(t, updateApple.OrgID)
+ assert.Equal(t, addApple.Id, updateApple.ID)
+ assert.Equal(t, name, updateApple.Name)
+ assert.Equal(t, domain.IDPTypeApple.String(), updateApple.Type)
+ assert.Equal(t, true, updateApple.AllowLinking)
+ assert.Equal(t, true, updateApple.AllowCreation)
+ assert.Equal(t, true, updateApple.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionUserName.String(), updateApple.AllowAutoLinking)
+ assert.WithinRange(t, updateApple.UpdatedAt, beforeCreate, afterCreate)
+
+ // apple
+ assert.Equal(t, "new_clientID", updateApple.ClientID)
+ assert.Equal(t, "new_teamID", updateApple.TeamID)
+ assert.Equal(t, "new_kKeyId", updateApple.KeyID)
+ assert.NotEqual(t, apple.PrivateKey, updateApple.PrivateKey)
+ assert.Equal(t, []string{"new_scope"}, updateApple.Scopes)
+ }, retryDuration, tick)
+ })
+
+ t.Run("test instance saml added reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+ federatedLogoutEnabled := false
+
+ // add saml
+ beforeCreate := time.Now()
+ addSAML, err := AdminClient.AddSAMLProvider(CTX, &admin.AddSAMLProviderRequest{
+ Name: name,
+ Metadata: &admin.AddSAMLProviderRequest_MetadataXml{
+ MetadataXml: validSAMLMetadata1,
+ },
+ Binding: idp.SAMLBinding_SAML_BINDING_POST,
+ WithSignedRequest: false,
+ TransientMappingAttributeName: &name,
+ FederatedLogoutEnabled: &federatedLogoutEnabled,
+ NameIdFormat: idp.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_TRANSIENT.Enum(),
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ saml, err := idpRepo.GetSAML(CTX, idpRepo.IDCondition(addSAML.Id), instanceID, nil)
+ require.NoError(t, err)
+
+ // event instance.idp.saml.added
+ // idp
+ assert.Equal(t, instanceID, saml.InstanceID)
+ assert.Nil(t, saml.OrgID)
+ assert.Equal(t, addSAML.Id, saml.ID)
+ assert.Equal(t, name, saml.Name)
+ assert.Equal(t, domain.IDPTypeSAML.String(), saml.Type)
+ assert.Equal(t, false, saml.AllowLinking)
+ assert.Equal(t, false, saml.AllowCreation)
+ assert.Equal(t, false, saml.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionEmail.String(), saml.AllowAutoLinking)
+ assert.WithinRange(t, saml.CreatedAt, beforeCreate, afterCreate)
+ assert.WithinRange(t, saml.UpdatedAt, beforeCreate, afterCreate)
+
+ // saml
+ assert.Equal(t, validSAMLMetadata1, saml.Metadata)
+ assert.NotNil(t, saml.Key)
+ assert.NotNil(t, saml.Certificate)
+ assert.NotNil(t, saml.Binding)
+ assert.Equal(t, false, saml.WithSignedRequest)
+ assert.Equal(t, zitadel_internal_domain.SAMLNameIDFormatTransient, *saml.NameIDFormat)
+ assert.Equal(t, name, saml.TransientMappingAttributeName)
+ assert.Equal(t, false, saml.FederatedLogoutEnabled)
+ }, retryDuration, tick)
+ })
+
+ t.Run("test instance saml changed reduces", func(t *testing.T) {
+ name := gofakeit.Name()
+ federatedLogoutEnabled := false
+
+ // add saml
+ addSAML, err := AdminClient.AddSAMLProvider(CTX, &admin.AddSAMLProviderRequest{
+ Name: name,
+ Metadata: &admin.AddSAMLProviderRequest_MetadataXml{
+ MetadataXml: validSAMLMetadata1,
+ },
+ Binding: idp.SAMLBinding_SAML_BINDING_POST,
+ WithSignedRequest: false,
+ TransientMappingAttributeName: &name,
+ FederatedLogoutEnabled: &federatedLogoutEnabled,
+ NameIdFormat: idp.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_TRANSIENT.Enum(),
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: false,
+ IsCreationAllowed: false,
+ IsAutoCreation: false,
+ IsAutoUpdate: false,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL,
+ },
+ })
+ require.NoError(t, err)
+
+ idpRepo := repository.IDProviderRepository(pool)
+
+ var saml *domain.IDPSAML
+ retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ saml, err = idpRepo.GetSAML(CTX, idpRepo.IDCondition(addSAML.Id), instanceID, nil)
+ require.NoError(t, err)
+ assert.Equal(t, addSAML.Id, saml.ID)
+ }, retryDuration, tick)
+
+ name = "new_" + name
+ federatedLogoutEnabled = true
+ // change saml
+ beforeCreate := time.Now()
+ _, err = AdminClient.UpdateSAMLProvider(CTX, &admin.UpdateSAMLProviderRequest{
+ Id: addSAML.Id,
+ Name: name,
+ Metadata: &admin.UpdateSAMLProviderRequest_MetadataXml{
+ MetadataXml: validSAMLMetadata2,
+ },
+ Binding: idp.SAMLBinding_SAML_BINDING_ARTIFACT,
+ WithSignedRequest: true,
+ TransientMappingAttributeName: &name,
+ FederatedLogoutEnabled: &federatedLogoutEnabled,
+ NameIdFormat: idp.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_EMAIL_ADDRESS.Enum(),
+ ProviderOptions: &idp_grpc.Options{
+ IsLinkingAllowed: true,
+ IsCreationAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ AutoLinking: idp.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME,
+ },
+ })
+ afterCreate := time.Now()
+ require.NoError(t, err)
+
+ // check values for apple
+ retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Second*5)
+ assert.EventuallyWithT(t, func(t *assert.CollectT) {
+ updateSAML, err := idpRepo.GetSAML(CTX, idpRepo.IDCondition(addSAML.Id), instanceID, nil)
+ require.NoError(t, err)
+
+ // event instance.idp.saml.changed
+ // idp
+ assert.Equal(t, instanceID, updateSAML.InstanceID)
+ assert.Nil(t, updateSAML.OrgID)
+ assert.Equal(t, addSAML.Id, updateSAML.ID)
+ assert.Equal(t, name, updateSAML.Name)
+ assert.Equal(t, domain.IDPTypeSAML.String(), updateSAML.Type)
+ assert.Equal(t, true, updateSAML.AllowLinking)
+ assert.Equal(t, true, updateSAML.AllowCreation)
+ assert.Equal(t, true, updateSAML.AllowAutoUpdate)
+ assert.Equal(t, domain.IDPAutoLinkingOptionUserName.String(), updateSAML.AllowAutoLinking)
+ assert.WithinRange(t, updateSAML.UpdatedAt, beforeCreate, afterCreate)
+
+ // saml
+ assert.Equal(t, validSAMLMetadata2, updateSAML.Metadata)
+ assert.NotNil(t, updateSAML.Key)
+ // assert.NotEqual(t, saml.Key, updateSAML.Key) // https://github.com/zitadel/zitadel/issues/10414
+ assert.NotNil(t, updateSAML.Certificate)
+ // assert.NotEqual(t, saml.Certificate, updateSAML.Certificate) // https://github.com/zitadel/zitadel/issues/10414
+ assert.NotNil(t, updateSAML.Binding)
+ assert.NotEqual(t, saml.Binding, updateSAML.Binding)
+ assert.Equal(t, true, updateSAML.WithSignedRequest)
+ assert.Equal(t, zitadel_internal_domain.SAMLNameIDFormatEmailAddress, *updateSAML.NameIDFormat)
+ assert.Equal(t, name, updateSAML.TransientMappingAttributeName)
+ assert.Equal(t, true, updateSAML.FederatedLogoutEnabled)
+ }, retryDuration, tick)
+ })
}
diff --git a/backend/v3/storage/database/repository/id_provider.go b/backend/v3/storage/database/repository/id_provider.go
index 54ac2da9a6..3152eacad4 100644
--- a/backend/v3/storage/database/repository/id_provider.go
+++ b/backend/v3/storage/database/repository/id_provider.go
@@ -339,6 +339,50 @@ func (i *idProvider) GetLDAP(ctx context.Context, id domain.IDPIdentifierConditi
return ldap, nil
}
+func (i *idProvider) GetApple(ctx context.Context, id domain.IDPIdentifierCondition, instnaceID string, orgID *string) (*domain.IDPApple, error) {
+ apple := &domain.IDPApple{}
+ var err error
+
+ apple.IdentityProvider, err = i.Get(ctx, id, instnaceID, orgID)
+ if err != nil {
+ return nil, err
+ }
+
+ if apple.Type != domain.IDPTypeApple.String() {
+ // TODO
+ return nil, errors.New("WRONG TYPE")
+ }
+
+ err = json.Unmarshal([]byte(*apple.Payload), apple)
+ if err != nil {
+ return nil, err
+ }
+
+ return apple, nil
+}
+
+func (i *idProvider) GetSAML(ctx context.Context, id domain.IDPIdentifierCondition, instnaceID string, orgID *string) (*domain.IDPSAML, error) {
+ saml := &domain.IDPSAML{}
+ var err error
+
+ saml.IdentityProvider, err = i.Get(ctx, id, instnaceID, orgID)
+ if err != nil {
+ return nil, err
+ }
+
+ if saml.Type != domain.IDPTypeSAML.String() {
+ // TODO
+ return nil, errors.New("WRONG TYPE")
+ }
+
+ err = json.Unmarshal([]byte(*saml.Payload), saml)
+ if err != nil {
+ return nil, err
+ }
+
+ return saml, nil
+}
+
// -------------------------------------------------------------
// columns
// -------------------------------------------------------------
diff --git a/internal/query/projection/idp_template_relational.go b/internal/query/projection/idp_template_relational.go
index be50c8e1f3..ef9b20151c 100644
--- a/internal/query/projection/idp_template_relational.go
+++ b/internal/query/projection/idp_template_relational.go
@@ -3,7 +3,9 @@ package projection
import (
"context"
"encoding/json"
+ "fmt"
+ "github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database/dialect/postgres"
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
@@ -164,30 +166,30 @@ func (p *idpTemplateRelationalProjection) Reducers() []handler.AggregateReducer
Event: instance.LDAPIDPChangedEventType,
Reduce: p.reduceLDAPIDPChanged,
},
- // {
- // Event: instance.AppleIDPAddedEventType,
- // Reduce: p.reduceAppleIDPAdded,
- // },
- // {
- // Event: instance.AppleIDPChangedEventType,
- // Reduce: p.reduceAppleIDPChanged,
- // },
- // {
- // Event: instance.SAMLIDPAddedEventType,
- // Reduce: p.reduceSAMLIDPAdded,
- // },
- // {
- // Event: instance.SAMLIDPChangedEventType,
- // Reduce: p.reduceSAMLIDPChanged,
- // },
+ {
+ Event: instance.AppleIDPAddedEventType,
+ Reduce: p.reduceAppleIDPAdded,
+ },
+ {
+ Event: instance.AppleIDPChangedEventType,
+ Reduce: p.reduceAppleIDPChanged,
+ },
+ {
+ Event: instance.SAMLIDPAddedEventType,
+ Reduce: p.reduceSAMLIDPAdded,
+ },
+ {
+ Event: instance.SAMLIDPChangedEventType,
+ Reduce: p.reduceSAMLIDPChanged,
+ },
// {
// Event: instance.IDPConfigRemovedEventType,
// Reduce: p.reduceIDPConfigRemoved,
// },
- // {
- // Event: instance.IDPRemovedEventType,
- // Reduce: p.reduceIDPRemoved,
- // },
+ {
+ Event: instance.IDPRemovedEventType,
+ Reduce: p.reduceIDPRemoved,
+ },
// {
// Event: instance.InstanceRemovedEventType,
// Reduce: reduceInstanceRemovedHelper(IDPTemplateInstanceIDCol),
@@ -309,30 +311,30 @@ func (p *idpTemplateRelationalProjection) Reducers() []handler.AggregateReducer
Event: org.LDAPIDPChangedEventType,
Reduce: p.reduceLDAPIDPChanged,
},
- // {
- // Event: org.AppleIDPAddedEventType,
- // Reduce: p.reduceAppleIDPAdded,
- // },
- // {
- // Event: org.AppleIDPChangedEventType,
- // Reduce: p.reduceAppleIDPChanged,
- // },
- // {
- // Event: org.SAMLIDPAddedEventType,
- // Reduce: p.reduceSAMLIDPAdded,
- // },
- // {
- // Event: org.SAMLIDPChangedEventType,
- // Reduce: p.reduceSAMLIDPChanged,
- // },
+ {
+ Event: org.AppleIDPAddedEventType,
+ Reduce: p.reduceAppleIDPAdded,
+ },
+ {
+ Event: org.AppleIDPChangedEventType,
+ Reduce: p.reduceAppleIDPChanged,
+ },
+ {
+ Event: org.SAMLIDPAddedEventType,
+ Reduce: p.reduceSAMLIDPAdded,
+ },
+ {
+ Event: org.SAMLIDPChangedEventType,
+ Reduce: p.reduceSAMLIDPChanged,
+ },
// {
// Event: org.IDPConfigRemovedEventType,
// Reduce: p.reduceIDPConfigRemoved,
// },
- // {
- // Event: org.IDPRemovedEventType,
- // Reduce: p.reduceIDPRemoved,
- // },
+ {
+ Event: org.IDPRemovedEventType,
+ Reduce: p.reduceIDPRemoved,
+ },
// {
// Event: org.OrgRemovedEventType,
// Reduce: p.reduceOwnerRemoved,
@@ -1862,195 +1864,235 @@ func (p *idpTemplateRelationalProjection) reduceLDAPIDPChanged(event eventstore.
// ), nil
}
-// func (p *idpTemplateProjection) reduceSAMLIDPAdded(event eventstore.Event) (*handler.Statement, error) {
-// var idpEvent idp.SAMLIDPAddedEvent
-// var idpOwnerType domain.IdentityProviderType
-// switch e := event.(type) {
-// case *org.SAMLIDPAddedEvent:
-// idpEvent = e.SAMLIDPAddedEvent
-// idpOwnerType = domain.IdentityProviderTypeOrg
-// case *instance.SAMLIDPAddedEvent:
-// idpEvent = e.SAMLIDPAddedEvent
-// idpOwnerType = domain.IdentityProviderTypeSystem
-// default:
-// return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-9s02m1", "reduce.wrong.event.type %v", []eventstore.EventType{org.SAMLIDPAddedEventType, instance.SAMLIDPAddedEventType})
-// }
+func (p *idpTemplateRelationalProjection) reduceAppleIDPAdded(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.AppleIDPAddedEvent
+ switch e := event.(type) {
+ case *org.AppleIDPAddedEvent:
+ idpEvent = e.AppleIDPAddedEvent
+ case *instance.AppleIDPAddedEvent:
+ idpEvent = e.AppleIDPAddedEvent
+ default:
+ return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-YFvg3", "reduce.wrong.event.type %v", []eventstore.EventType{org.AppleIDPAddedEventType /*, instance.AppleIDPAddedEventType*/})
+ }
-// columns := []handler.Column{
-// handler.NewCol(SAMLIDCol, idpEvent.ID),
-// handler.NewCol(SAMLInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// handler.NewCol(SAMLMetadataCol, idpEvent.Metadata),
-// handler.NewCol(SAMLKeyCol, idpEvent.Key),
-// handler.NewCol(SAMLCertificateCol, idpEvent.Certificate),
-// handler.NewCol(SAMLBindingCol, idpEvent.Binding),
-// handler.NewCol(SAMLWithSignedRequestCol, idpEvent.WithSignedRequest),
-// handler.NewCol(SAMLTransientMappingAttributeName, idpEvent.TransientMappingAttributeName),
-// handler.NewCol(SAMLFederatedLogoutEnabled, idpEvent.FederatedLogoutEnabled),
-// }
-// if idpEvent.NameIDFormat != nil {
-// columns = append(columns, handler.NewCol(SAMLNameIDFormatCol, *idpEvent.NameIDFormat))
-// }
+ apple := db_domain.Apple{
+ ClientID: idpEvent.ClientID,
+ TeamID: idpEvent.TeamID,
+ KeyID: idpEvent.KeyID,
+ PrivateKey: idpEvent.PrivateKey,
+ Scopes: idpEvent.Scopes,
+ }
-// return handler.NewMultiStatement(
-// &idpEvent,
-// handler.AddCreateStatement(
-// []handler.Column{
-// handler.NewCol(IDPTemplateIDCol, idpEvent.ID),
-// handler.NewCol(IDPTemplateCreationDateCol, idpEvent.CreationDate()),
-// handler.NewCol(IDPTemplateChangeDateCol, idpEvent.CreationDate()),
-// handler.NewCol(IDPTemplateSequenceCol, idpEvent.Sequence()),
-// handler.NewCol(IDPTemplateResourceOwnerCol, idpEvent.Aggregate().ResourceOwner),
-// handler.NewCol(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// handler.NewCol(IDPTemplateStateCol, domain.IDPStateActive),
-// handler.NewCol(IDPTemplateNameCol, idpEvent.Name),
-// handler.NewCol(IDPTemplateOwnerTypeCol, idpOwnerType),
-// handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeSAML),
-// handler.NewCol(IDPTemplateIsCreationAllowedCol, idpEvent.IsCreationAllowed),
-// handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
-// handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
-// handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
-// handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
-// },
-// ),
-// handler.AddCreateStatement(
-// columns,
-// handler.WithTableSuffix(IDPTemplateSAMLSuffix),
-// ),
-// ), nil
-// }
+ payload, err := json.Marshal(apple)
+ if err != nil {
+ return nil, err
+ }
-// func (p *idpTemplateProjection) reduceSAMLIDPChanged(event eventstore.Event) (*handler.Statement, error) {
-// var idpEvent idp.SAMLIDPChangedEvent
-// switch e := event.(type) {
-// case *org.SAMLIDPChangedEvent:
-// idpEvent = e.SAMLIDPChangedEvent
-// case *instance.SAMLIDPChangedEvent:
-// idpEvent = e.SAMLIDPChangedEvent
-// default:
-// return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-o7c0fii4ad", "reduce.wrong.event.type %v", []eventstore.EventType{org.SAMLIDPChangedEventType, instance.SAMLIDPChangedEventType})
-// }
+ var orgId *string
+ if idpEvent.Aggregate().ResourceOwner != idpEvent.Agg.InstanceID {
+ orgId = &idpEvent.Aggregate().ResourceOwner
+ }
-// ops := make([]func(eventstore.Event) handler.Exec, 0, 2)
-// ops = append(ops,
-// handler.AddUpdateStatement(
-// reduceIDPChangedTemplateColumns(idpEvent.Name, idpEvent.CreationDate(), idpEvent.Sequence(), idpEvent.OptionChanges),
-// []handler.Condition{
-// handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
-// handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// },
-// ),
-// )
+ return handler.NewMultiStatement(
+ &idpEvent,
+ handler.AddCreateStatement(
+ []handler.Column{
+ handler.NewCol(IDPTemplateIDCol, idpEvent.ID),
+ handler.NewCol(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ handler.NewCol(IDPRelationalOrgId, orgId),
+ handler.NewCol(IDPTemplateNameCol, idpEvent.Name),
+ handler.NewCol(IDPTemplateTypeCol, db_domain.IDPTypeApple.String()),
+ handler.NewCol(IDPTemplateStateCol, db_domain.IDPStateActive.String()),
+ handler.NewCol(IDPRelationalAllowCreationCol, idpEvent.IsCreationAllowed),
+ handler.NewCol(IDPRelationalAllowLinkingCol, idpEvent.IsLinkingAllowed),
+ handler.NewCol(IDPRelationalAllowAutoCreationCol, idpEvent.IsAutoCreation),
+ handler.NewCol(IDPRelationalAllowAutoUpdateCol, idpEvent.IsAutoUpdate),
+ handler.NewCol(IDPRelationalAllowAutoLinkingCol, db_domain.IDPAutoLinkingOption(idpEvent.AutoLinkingOption).String()),
+ handler.NewCol(CreatedAt, idpEvent.CreationDate()),
+ handler.NewCol(IDPRelationalPayloadCol, payload),
+ },
+ ),
+ ), nil
+}
-// SAMLCols := reduceSAMLIDPChangedColumns(idpEvent)
-// if len(SAMLCols) > 0 {
-// ops = append(ops,
-// handler.AddUpdateStatement(
-// SAMLCols,
-// []handler.Condition{
-// handler.NewCond(SAMLIDCol, idpEvent.ID),
-// handler.NewCond(SAMLInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// },
-// handler.WithTableSuffix(IDPTemplateSAMLSuffix),
-// ),
-// )
-// }
+func (p *idpTemplateRelationalProjection) reduceAppleIDPChanged(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.AppleIDPChangedEvent
+ switch e := event.(type) {
+ case *org.AppleIDPChangedEvent:
+ idpEvent = e.AppleIDPChangedEvent
+ case *instance.AppleIDPChangedEvent:
+ idpEvent = e.AppleIDPChangedEvent
+ default:
+ return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-YBez3", "reduce.wrong.event.type %v", []eventstore.EventType{org.AppleIDPChangedEventType /*, instance.AppleIDPChangedEventType*/})
+ }
-// return handler.NewMultiStatement(
-// &idpEvent,
-// ops...,
-// ), nil
-// }
+ var orgId *string
+ if idpEvent.Aggregate().ResourceOwner != idpEvent.Agg.InstanceID {
+ orgId = &idpEvent.Aggregate().ResourceOwner
+ }
-// func (p *idpTemplateProjection) reduceAppleIDPAdded(event eventstore.Event) (*handler.Statement, error) {
-// var idpEvent idp.AppleIDPAddedEvent
-// var idpOwnerType domain.IdentityProviderType
-// switch e := event.(type) {
-// case *org.AppleIDPAddedEvent:
-// idpEvent = e.AppleIDPAddedEvent
-// idpOwnerType = domain.IdentityProviderTypeOrg
-// case *instance.AppleIDPAddedEvent:
-// idpEvent = e.AppleIDPAddedEvent
-// idpOwnerType = domain.IdentityProviderTypeSystem
-// default:
-// return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-SFvg3", "reduce.wrong.event.type %v", []eventstore.EventType{org.AppleIDPAddedEventType /*, instance.AppleIDPAddedEventType*/})
-// }
+ apple, err := p.idpRepo.GetApple(context.Background(), p.idpRepo.IDCondition(idpEvent.ID), idpEvent.Agg.InstanceID, orgId)
+ if err != nil {
+ return nil, err
+ }
-// return handler.NewMultiStatement(
-// &idpEvent,
-// handler.AddCreateStatement(
-// []handler.Column{
-// handler.NewCol(IDPTemplateIDCol, idpEvent.ID),
-// handler.NewCol(IDPTemplateCreationDateCol, idpEvent.CreationDate()),
-// handler.NewCol(IDPTemplateChangeDateCol, idpEvent.CreationDate()),
-// handler.NewCol(IDPTemplateSequenceCol, idpEvent.Sequence()),
-// handler.NewCol(IDPTemplateResourceOwnerCol, idpEvent.Aggregate().ResourceOwner),
-// handler.NewCol(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// handler.NewCol(IDPTemplateStateCol, domain.IDPStateActive),
-// handler.NewCol(IDPTemplateNameCol, idpEvent.Name),
-// handler.NewCol(IDPTemplateOwnerTypeCol, idpOwnerType),
-// handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeApple),
-// handler.NewCol(IDPTemplateIsCreationAllowedCol, idpEvent.IsCreationAllowed),
-// handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
-// handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
-// handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
-// handler.NewCol(IDPTemplateAutoLinkingCol, idpEvent.AutoLinkingOption),
-// },
-// ),
-// handler.AddCreateStatement(
-// []handler.Column{
-// handler.NewCol(AppleIDCol, idpEvent.ID),
-// handler.NewCol(AppleInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// handler.NewCol(AppleClientIDCol, idpEvent.ClientID),
-// handler.NewCol(AppleTeamIDCol, idpEvent.TeamID),
-// handler.NewCol(AppleKeyIDCol, idpEvent.KeyID),
-// handler.NewCol(ApplePrivateKeyCol, idpEvent.PrivateKey),
-// handler.NewCol(AppleScopesCol, database.TextArray[string](idpEvent.Scopes)),
-// },
-// handler.WithTableSuffix(IDPTemplateAppleSuffix),
-// ),
-// ), nil
-// }
+ columns := make([]handler.Column, 0, 7)
+ reduceIDPRelationalChangedTemplateColumns(idpEvent.Name, idpEvent.OptionChanges, &columns)
-// func (p *idpTemplateProjection) reduceAppleIDPChanged(event eventstore.Event) (*handler.Statement, error) {
-// var idpEvent idp.AppleIDPChangedEvent
-// switch e := event.(type) {
-// case *org.AppleIDPChangedEvent:
-// idpEvent = e.AppleIDPChangedEvent
-// case *instance.AppleIDPChangedEvent:
-// idpEvent = e.AppleIDPChangedEvent
-// default:
-// return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-GBez3", "reduce.wrong.event.type %v", []eventstore.EventType{org.AppleIDPChangedEventType /*, instance.AppleIDPChangedEventType*/})
-// }
+ payload := &apple.Apple
+ payloadChanged := reduceAppleIDPRelationalChangedColumns(payload, &idpEvent)
+ if payloadChanged {
+ payload, err := json.Marshal(payload)
+ if err != nil {
+ return nil, err
+ }
+ columns = append(columns, handler.NewCol(IDPRelationalPayloadCol, payload))
+ }
-// ops := make([]func(eventstore.Event) handler.Exec, 0, 2)
-// ops = append(ops,
-// handler.AddUpdateStatement(
-// reduceIDPChangedTemplateColumns(idpEvent.Name, idpEvent.CreationDate(), idpEvent.Sequence(), idpEvent.OptionChanges),
-// []handler.Condition{
-// handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
-// handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// },
-// ),
-// )
-// appleCols := reduceAppleIDPChangedColumns(idpEvent)
-// if len(appleCols) > 0 {
-// ops = append(ops,
-// handler.AddUpdateStatement(
-// appleCols,
-// []handler.Condition{
-// handler.NewCond(AppleIDCol, idpEvent.ID),
-// handler.NewCond(AppleInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// },
-// handler.WithTableSuffix(IDPTemplateAppleSuffix),
-// ),
-// )
-// }
+ return handler.NewMultiStatement(
+ &idpEvent,
+ handler.AddUpdateStatement(
+ columns,
+ []handler.Condition{
+ handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
+ handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ handler.NewCond(IDPRelationalOrgId, orgId),
+ },
+ ),
+ ), nil
+}
-// return handler.NewMultiStatement(
-// &idpEvent,
-// ops...,
-// ), nil
-// }
+func (p *idpTemplateRelationalProjection) reduceSAMLIDPAdded(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.SAMLIDPAddedEvent
+ switch e := event.(type) {
+ case *org.SAMLIDPAddedEvent:
+ idpEvent = e.SAMLIDPAddedEvent
+ case *instance.SAMLIDPAddedEvent:
+ idpEvent = e.SAMLIDPAddedEvent
+ default:
+ return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-Ys02m1", "reduce.wrong.event.type %v", []eventstore.EventType{org.SAMLIDPAddedEventType, instance.SAMLIDPAddedEventType})
+ }
+
+ fmt.Printf("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> idpEvent.NameIDFormat = %+v\n", idpEvent.NameIDFormat)
+
+ saml := db_domain.SAML{
+ Metadata: idpEvent.Metadata,
+ Key: idpEvent.Key,
+ Certificate: idpEvent.Certificate,
+ Binding: idpEvent.Binding,
+ WithSignedRequest: idpEvent.WithSignedRequest,
+ NameIDFormat: idpEvent.NameIDFormat,
+ TransientMappingAttributeName: idpEvent.TransientMappingAttributeName,
+ FederatedLogoutEnabled: idpEvent.FederatedLogoutEnabled,
+ }
+
+ payload, err := json.Marshal(saml)
+ if err != nil {
+ return nil, err
+ }
+
+ var orgId *string
+ if idpEvent.Aggregate().ResourceOwner != idpEvent.Agg.InstanceID {
+ orgId = &idpEvent.Aggregate().ResourceOwner
+ }
+
+ return handler.NewMultiStatement(
+ &idpEvent,
+ handler.AddCreateStatement(
+ []handler.Column{
+ handler.NewCol(IDPTemplateIDCol, idpEvent.ID),
+ handler.NewCol(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ handler.NewCol(IDPRelationalOrgId, orgId),
+ handler.NewCol(IDPTemplateNameCol, idpEvent.Name),
+ handler.NewCol(IDPTemplateTypeCol, db_domain.IDPTypeSAML.String()),
+ handler.NewCol(IDPTemplateStateCol, db_domain.IDPStateActive.String()),
+ handler.NewCol(IDPRelationalAllowCreationCol, idpEvent.IsCreationAllowed),
+ handler.NewCol(IDPRelationalAllowLinkingCol, idpEvent.IsLinkingAllowed),
+ handler.NewCol(IDPRelationalAllowAutoCreationCol, idpEvent.IsAutoCreation),
+ handler.NewCol(IDPRelationalAllowAutoUpdateCol, idpEvent.IsAutoUpdate),
+ handler.NewCol(IDPRelationalAllowAutoLinkingCol, db_domain.IDPAutoLinkingOption(idpEvent.AutoLinkingOption).String()),
+ handler.NewCol(CreatedAt, idpEvent.CreationDate()),
+ handler.NewCol(IDPRelationalPayloadCol, payload),
+ },
+ ),
+ ), nil
+}
+
+func (p *idpTemplateRelationalProjection) reduceSAMLIDPChanged(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.SAMLIDPChangedEvent
+ switch e := event.(type) {
+ case *org.SAMLIDPChangedEvent:
+ idpEvent = e.SAMLIDPChangedEvent
+ case *instance.SAMLIDPChangedEvent:
+ idpEvent = e.SAMLIDPChangedEvent
+ default:
+ return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-Y7c0fii4ad", "reduce.wrong.event.type %v", []eventstore.EventType{org.SAMLIDPChangedEventType, instance.SAMLIDPChangedEventType})
+ }
+
+ var orgId *string
+ if idpEvent.Aggregate().ResourceOwner != idpEvent.Agg.InstanceID {
+ orgId = &idpEvent.Aggregate().ResourceOwner
+ }
+
+ saml, err := p.idpRepo.GetSAML(context.Background(), p.idpRepo.IDCondition(idpEvent.ID), idpEvent.Agg.InstanceID, orgId)
+ if err != nil {
+ return nil, err
+ }
+
+ columns := make([]handler.Column, 0, 7)
+ reduceIDPRelationalChangedTemplateColumns(idpEvent.Name, idpEvent.OptionChanges, &columns)
+
+ payload := &saml.SAML
+ payloadChanged := reduceSAMLIDPRelationalChangedColumns(payload, &idpEvent)
+ if payloadChanged {
+ payload, err := json.Marshal(payload)
+ if err != nil {
+ return nil, err
+ }
+ columns = append(columns, handler.NewCol(IDPRelationalPayloadCol, payload))
+ }
+
+ return handler.NewMultiStatement(
+ &idpEvent,
+ handler.AddUpdateStatement(
+ columns,
+ []handler.Condition{
+ handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
+ handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ handler.NewCond(IDPRelationalOrgId, orgId),
+ },
+ ),
+ ), nil
+
+ // ops := make([]func(eventstore.Event) handler.Exec, 0, 2)
+ // ops = append(ops,
+ // handler.AddUpdateStatement(
+ // reduceIDPChangedTemplateColumns(idpEvent.Name, idpEvent.CreationDate(), idpEvent.Sequence(), idpEvent.OptionChanges),
+ // []handler.Condition{
+ // handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
+ // handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ // },
+ // ),
+ // )
+
+ // if len(SAMLCols) > 0 {
+ // ops = append(ops,
+ // handler.AddUpdateStatement(
+ // SAMLCols,
+ // []handler.Condition{
+ // handler.NewCond(SAMLIDCol, idpEvent.ID),
+ // handler.NewCond(SAMLInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ // },
+ // handler.WithTableSuffix(IDPTemplateSAMLSuffix),
+ // ),
+ // )
+ // }
+
+ // return handler.NewMultiStatement(
+ // &idpEvent,
+ // ops...,
+ // ), nil
+}
// func (p *idpTemplateProjection) reduceIDPConfigRemoved(event eventstore.Event) (*handler.Statement, error) {
// var idpEvent idpconfig.IDPConfigRemovedEvent
@@ -2072,25 +2114,25 @@ func (p *idpTemplateRelationalProjection) reduceLDAPIDPChanged(event eventstore.
// ), nil
// }
-// func (p *idpTemplateProjection) reduceIDPRemoved(event eventstore.Event) (*handler.Statement, error) {
-// var idpEvent idp.RemovedEvent
-// switch e := event.(type) {
-// case *org.IDPRemovedEvent:
-// idpEvent = e.RemovedEvent
-// case *instance.IDPRemovedEvent:
-// idpEvent = e.RemovedEvent
-// default:
-// return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-xbcvwin2", "reduce.wrong.event.type %v", []eventstore.EventType{org.IDPRemovedEventType, instance.IDPRemovedEventType})
-// }
+func (p *idpTemplateRelationalProjection) reduceIDPRemoved(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.RemovedEvent
+ switch e := event.(type) {
+ case *org.IDPRemovedEvent:
+ idpEvent = e.RemovedEvent
+ case *instance.IDPRemovedEvent:
+ idpEvent = e.RemovedEvent
+ default:
+ return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-xbcvwin2", "reduce.wrong.event.type %v", []eventstore.EventType{org.IDPRemovedEventType, instance.IDPRemovedEventType})
+ }
-// return handler.NewDeleteStatement(
-// &idpEvent,
-// []handler.Condition{
-// handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
-// handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
-// },
-// ), nil
-// }
+ return handler.NewDeleteStatement(
+ &idpEvent,
+ []handler.Condition{
+ handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
+ handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ },
+ ), nil
+}
// func (p *idpTemplateProjection) reduceOwnerRemoved(event eventstore.Event) (*handler.Statement, error) {
// e, ok := event.(*org.OrgRemovedEvent)
@@ -2757,3 +2799,68 @@ func reduceLDAPIDPRelationalChangedColumns(payload *db_domain.LDAP, idpEvent *id
}
return payloadChange
}
+
+func reduceAppleIDPRelationalChangedColumns(payload *domain.Apple, idpEvent *idp.AppleIDPChangedEvent) bool {
+ payloadChange := false
+ if idpEvent.ClientID != nil {
+ payloadChange = true
+ payload.ClientID = *idpEvent.ClientID
+ }
+ if idpEvent.TeamID != nil {
+ payloadChange = true
+ payload.TeamID = *idpEvent.TeamID
+ }
+ if idpEvent.KeyID != nil {
+ payloadChange = true
+ payload.KeyID = *idpEvent.KeyID
+ }
+ if idpEvent.PrivateKey != nil {
+ payloadChange = true
+ payload.PrivateKey = idpEvent.PrivateKey
+ }
+ if idpEvent.Scopes != nil {
+ payloadChange = true
+ payload.Scopes = idpEvent.Scopes
+ }
+ return payloadChange
+}
+
+func reduceSAMLIDPRelationalChangedColumns(payload *domain.SAML, idpEvent *idp.SAMLIDPChangedEvent) bool {
+ payloadChange := false
+ if idpEvent.Metadata != nil {
+ payloadChange = true
+ payload.Metadata = idpEvent.Metadata
+ fmt.Println("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> METTTADATA")
+ }
+ if idpEvent.Key != nil {
+ payloadChange = true
+ payload.Key = idpEvent.Key
+ fmt.Println("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> KEEEEEEEEEEEEEEY")
+ }
+ if idpEvent.Certificate != nil {
+ payloadChange = true
+ payload.Certificate = idpEvent.Certificate
+ }
+ if idpEvent.Binding != nil {
+ payloadChange = true
+ payload.Binding = *idpEvent.Binding
+ fmt.Println("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> BINDING")
+ }
+ if idpEvent.WithSignedRequest != nil {
+ payloadChange = true
+ payload.WithSignedRequest = *idpEvent.WithSignedRequest
+ }
+ if idpEvent.NameIDFormat != nil {
+ payloadChange = true
+ payload.NameIDFormat = idpEvent.NameIDFormat
+ }
+ if idpEvent.TransientMappingAttributeName != nil {
+ payloadChange = true
+ payload.TransientMappingAttributeName = *idpEvent.TransientMappingAttributeName
+ }
+ if idpEvent.FederatedLogoutEnabled != nil {
+ payloadChange = true
+ payload.FederatedLogoutEnabled = *idpEvent.FederatedLogoutEnabled
+ }
+ return payloadChange
+}