diff --git a/internal/api/grpc/admin/idp.go b/internal/api/grpc/admin/idp.go
index 1e0e9ccdf5..dab331b793 100644
--- a/internal/api/grpc/admin/idp.go
+++ b/internal/api/grpc/admin/idp.go
@@ -283,6 +283,48 @@ func (s *Server) UpdateGitHubEnterpriseServerProvider(ctx context.Context, req *
}, nil
}
+func (s *Server) AddGitLabProvider(ctx context.Context, req *admin_pb.AddGitLabProviderRequest) (*admin_pb.AddGitLabProviderResponse, error) {
+ id, details, err := s.command.AddInstanceGitLabProvider(ctx, addGitLabProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &admin_pb.AddGitLabProviderResponse{
+ Id: id,
+ Details: object_pb.DomainToAddDetailsPb(details),
+ }, nil
+}
+
+func (s *Server) UpdateGitLabProvider(ctx context.Context, req *admin_pb.UpdateGitLabProviderRequest) (*admin_pb.UpdateGitLabProviderResponse, error) {
+ details, err := s.command.UpdateInstanceGitLabProvider(ctx, req.Id, updateGitLabProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &admin_pb.UpdateGitLabProviderResponse{
+ Details: object_pb.DomainToChangeDetailsPb(details),
+ }, nil
+}
+
+func (s *Server) AddGitLabSelfHostedProvider(ctx context.Context, req *admin_pb.AddGitLabSelfHostedProviderRequest) (*admin_pb.AddGitLabSelfHostedProviderResponse, error) {
+ id, details, err := s.command.AddInstanceGitLabSelfHostedProvider(ctx, addGitLabSelfHostedProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &admin_pb.AddGitLabSelfHostedProviderResponse{
+ Id: id,
+ Details: object_pb.DomainToAddDetailsPb(details),
+ }, nil
+}
+
+func (s *Server) UpdateGitLabSelfHostedProvider(ctx context.Context, req *admin_pb.UpdateGitLabSelfHostedProviderRequest) (*admin_pb.UpdateGitLabSelfHostedProviderResponse, error) {
+ details, err := s.command.UpdateInstanceGitLabSelfHostedProvider(ctx, req.Id, updateGitLabSelfHostedProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &admin_pb.UpdateGitLabSelfHostedProviderResponse{
+ Details: object_pb.DomainToChangeDetailsPb(details),
+ }, nil
+}
+
func (s *Server) AddGoogleProvider(ctx context.Context, req *admin_pb.AddGoogleProviderRequest) (*admin_pb.AddGoogleProviderResponse, error) {
id, details, err := s.command.AddInstanceGoogleProvider(ctx, addGoogleProviderToCommand(req))
if err != nil {
diff --git a/internal/api/grpc/admin/idp_converter.go b/internal/api/grpc/admin/idp_converter.go
index 48cc17cfe8..9a46f21069 100644
--- a/internal/api/grpc/admin/idp_converter.go
+++ b/internal/api/grpc/admin/idp_converter.go
@@ -319,6 +319,48 @@ func updateGitHubEnterpriseProviderToCommand(req *admin_pb.UpdateGitHubEnterpris
}
}
+func addGitLabProviderToCommand(req *admin_pb.AddGitLabProviderRequest) command.GitLabProvider {
+ return command.GitLabProvider{
+ Name: req.Name,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
+func updateGitLabProviderToCommand(req *admin_pb.UpdateGitLabProviderRequest) command.GitLabProvider {
+ return command.GitLabProvider{
+ Name: req.Name,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
+func addGitLabSelfHostedProviderToCommand(req *admin_pb.AddGitLabSelfHostedProviderRequest) command.GitLabSelfHostedProvider {
+ return command.GitLabSelfHostedProvider{
+ Name: req.Name,
+ Issuer: req.Issuer,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
+func updateGitLabSelfHostedProviderToCommand(req *admin_pb.UpdateGitLabSelfHostedProviderRequest) command.GitLabSelfHostedProvider {
+ return command.GitLabSelfHostedProvider{
+ Name: req.Name,
+ Issuer: req.Issuer,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
func addGoogleProviderToCommand(req *admin_pb.AddGoogleProviderRequest) command.GoogleProvider {
return command.GoogleProvider{
Name: req.Name,
diff --git a/internal/api/grpc/idp/converter.go b/internal/api/grpc/idp/converter.go
index fb17ae044b..5dbd53c553 100644
--- a/internal/api/grpc/idp/converter.go
+++ b/internal/api/grpc/idp/converter.go
@@ -420,6 +420,14 @@ func configToPb(config *query.IDPTemplate) *idp_pb.ProviderConfig {
githubEnterpriseConfigToPb(providerConfig, config.GitHubEnterpriseIDPTemplate)
return providerConfig
}
+ if config.GitLabIDPTemplate != nil {
+ gitlabConfigToPb(providerConfig, config.GitLabIDPTemplate)
+ return providerConfig
+ }
+ if config.GitLabSelfHostedIDPTemplate != nil {
+ gitlabSelfHostedConfigToPb(providerConfig, config.GitLabSelfHostedIDPTemplate)
+ return providerConfig
+ }
if config.GoogleIDPTemplate != nil {
googleConfigToPb(providerConfig, config.GoogleIDPTemplate)
return providerConfig
@@ -486,6 +494,25 @@ func githubEnterpriseConfigToPb(providerConfig *idp_pb.ProviderConfig, template
}
}
+func gitlabConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.GitLabIDPTemplate) {
+ providerConfig.Config = &idp_pb.ProviderConfig_Gitlab{
+ Gitlab: &idp_pb.GitLabConfig{
+ ClientId: template.ClientID,
+ Scopes: template.Scopes,
+ },
+ }
+}
+
+func gitlabSelfHostedConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.GitLabSelfHostedIDPTemplate) {
+ providerConfig.Config = &idp_pb.ProviderConfig_GitlabSelfHosted{
+ GitlabSelfHosted: &idp_pb.GitLabSelfHostedConfig{
+ ClientId: template.ClientID,
+ Issuer: template.Issuer,
+ Scopes: template.Scopes,
+ },
+ }
+}
+
func googleConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.GoogleIDPTemplate) {
providerConfig.Config = &idp_pb.ProviderConfig_Google{
Google: &idp_pb.GoogleConfig{
diff --git a/internal/api/grpc/management/idp.go b/internal/api/grpc/management/idp.go
index 7c787eb7e2..62e0e9a91b 100644
--- a/internal/api/grpc/management/idp.go
+++ b/internal/api/grpc/management/idp.go
@@ -275,6 +275,48 @@ func (s *Server) UpdateGitHubEnterpriseServerProvider(ctx context.Context, req *
}, nil
}
+func (s *Server) AddGitLabProvider(ctx context.Context, req *mgmt_pb.AddGitLabProviderRequest) (*mgmt_pb.AddGitLabProviderResponse, error) {
+ id, details, err := s.command.AddOrgGitLabProvider(ctx, authz.GetCtxData(ctx).OrgID, addGitLabProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &mgmt_pb.AddGitLabProviderResponse{
+ Id: id,
+ Details: object_pb.DomainToAddDetailsPb(details),
+ }, nil
+}
+
+func (s *Server) UpdateGitLabProvider(ctx context.Context, req *mgmt_pb.UpdateGitLabProviderRequest) (*mgmt_pb.UpdateGitLabProviderResponse, error) {
+ details, err := s.command.UpdateOrgGitLabProvider(ctx, authz.GetCtxData(ctx).OrgID, req.Id, updateGitLabProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &mgmt_pb.UpdateGitLabProviderResponse{
+ Details: object_pb.DomainToChangeDetailsPb(details),
+ }, nil
+}
+
+func (s *Server) AddGitLabSelfHostedProvider(ctx context.Context, req *mgmt_pb.AddGitLabSelfHostedProviderRequest) (*mgmt_pb.AddGitLabSelfHostedProviderResponse, error) {
+ id, details, err := s.command.AddOrgGitLabSelfHostedProvider(ctx, authz.GetCtxData(ctx).OrgID, addGitLabSelfHostedProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &mgmt_pb.AddGitLabSelfHostedProviderResponse{
+ Id: id,
+ Details: object_pb.DomainToAddDetailsPb(details),
+ }, nil
+}
+
+func (s *Server) UpdateGitLabSelfHostedProvider(ctx context.Context, req *mgmt_pb.UpdateGitLabSelfHostedProviderRequest) (*mgmt_pb.UpdateGitLabSelfHostedProviderResponse, error) {
+ details, err := s.command.UpdateOrgGitLabSelfHostedProvider(ctx, authz.GetCtxData(ctx).OrgID, req.Id, updateGitLabSelfHostedProviderToCommand(req))
+ if err != nil {
+ return nil, err
+ }
+ return &mgmt_pb.UpdateGitLabSelfHostedProviderResponse{
+ Details: object_pb.DomainToChangeDetailsPb(details),
+ }, nil
+}
+
func (s *Server) AddGoogleProvider(ctx context.Context, req *mgmt_pb.AddGoogleProviderRequest) (*mgmt_pb.AddGoogleProviderResponse, error) {
id, details, err := s.command.AddOrgGoogleProvider(ctx, authz.GetCtxData(ctx).OrgID, addGoogleProviderToCommand(req))
if err != nil {
diff --git a/internal/api/grpc/management/idp_converter.go b/internal/api/grpc/management/idp_converter.go
index b402ee5e07..f2466c8a9b 100644
--- a/internal/api/grpc/management/idp_converter.go
+++ b/internal/api/grpc/management/idp_converter.go
@@ -336,6 +336,48 @@ func updateGitHubEnterpriseProviderToCommand(req *mgmt_pb.UpdateGitHubEnterprise
}
}
+func addGitLabProviderToCommand(req *mgmt_pb.AddGitLabProviderRequest) command.GitLabProvider {
+ return command.GitLabProvider{
+ Name: req.Name,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
+func updateGitLabProviderToCommand(req *mgmt_pb.UpdateGitLabProviderRequest) command.GitLabProvider {
+ return command.GitLabProvider{
+ Name: req.Name,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
+func addGitLabSelfHostedProviderToCommand(req *mgmt_pb.AddGitLabSelfHostedProviderRequest) command.GitLabSelfHostedProvider {
+ return command.GitLabSelfHostedProvider{
+ Name: req.Name,
+ Issuer: req.Issuer,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
+func updateGitLabSelfHostedProviderToCommand(req *mgmt_pb.UpdateGitLabSelfHostedProviderRequest) command.GitLabSelfHostedProvider {
+ return command.GitLabSelfHostedProvider{
+ Name: req.Name,
+ Issuer: req.Issuer,
+ ClientID: req.ClientId,
+ ClientSecret: req.ClientSecret,
+ Scopes: req.Scopes,
+ IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
+ }
+}
+
func addGoogleProviderToCommand(req *mgmt_pb.AddGoogleProviderRequest) command.GoogleProvider {
return command.GoogleProvider{
Name: req.Name,
diff --git a/internal/api/ui/login/external_provider_handler.go b/internal/api/ui/login/external_provider_handler.go
index 42ee14396d..5ea64e0bae 100644
--- a/internal/api/ui/login/external_provider_handler.go
+++ b/internal/api/ui/login/external_provider_handler.go
@@ -19,6 +19,7 @@ import (
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/idp/providers/github"
+ "github.com/zitadel/zitadel/internal/idp/providers/gitlab"
"github.com/zitadel/zitadel/internal/idp/providers/google"
"github.com/zitadel/zitadel/internal/idp/providers/jwt"
"github.com/zitadel/zitadel/internal/idp/providers/oauth"
@@ -146,12 +147,14 @@ func (l *Login) handleIDP(w http.ResponseWriter, r *http.Request, authReq *domai
provider, err = l.githubProvider(r.Context(), identityProvider)
case domain.IDPTypeGitHubEnterprise:
provider, err = l.githubEnterpriseProvider(r.Context(), identityProvider)
+ case domain.IDPTypeGitLab:
+ provider, err = l.gitlabProvider(r.Context(), identityProvider)
+ case domain.IDPTypeGitLabSelfHosted:
+ provider, err = l.gitlabSelfHostedProvider(r.Context(), identityProvider)
case domain.IDPTypeGoogle:
provider, err = l.googleProvider(r.Context(), identityProvider)
case domain.IDPTypeLDAP,
domain.IDPTypeAzureAD,
- domain.IDPTypeGitLab,
- domain.IDPTypeGitLabSelfHosted,
domain.IDPTypeUnspecified:
fallthrough
default:
@@ -221,6 +224,20 @@ func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Reque
return
}
session = &oauth.Session{Provider: provider.(*github.Provider).Provider, Code: data.Code}
+ case domain.IDPTypeGitLab:
+ provider, err = l.gitlabProvider(r.Context(), identityProvider)
+ if err != nil {
+ l.externalAuthFailed(w, r, authReq, nil, nil, err)
+ return
+ }
+ session = &openid.Session{Provider: provider.(*gitlab.Provider).Provider, Code: data.Code}
+ case domain.IDPTypeGitLabSelfHosted:
+ provider, err = l.gitlabSelfHostedProvider(r.Context(), identityProvider)
+ if err != nil {
+ l.externalAuthFailed(w, r, authReq, nil, nil, err)
+ return
+ }
+ session = &openid.Session{Provider: provider.(*gitlab.Provider).Provider, Code: data.Code}
case domain.IDPTypeGoogle:
provider, err = l.googleProvider(r.Context(), identityProvider)
if err != nil {
@@ -231,8 +248,6 @@ func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Reque
case domain.IDPTypeJWT,
domain.IDPTypeLDAP,
domain.IDPTypeAzureAD,
- domain.IDPTypeGitLab,
- domain.IDPTypeGitLabSelfHosted,
domain.IDPTypeUnspecified:
fallthrough
default:
@@ -609,6 +624,7 @@ func (l *Login) oidcProvider(ctx context.Context, identityProvider *query.IDPTem
l.baseURL(ctx)+EndpointExternalLoginCallback,
identityProvider.OIDCIDPTemplate.Scopes,
openid.DefaultMapper,
+ openid.WithSelectAccount(),
)
}
@@ -678,6 +694,34 @@ func (l *Login) githubEnterpriseProvider(ctx context.Context, identityProvider *
)
}
+func (l *Login) gitlabProvider(ctx context.Context, identityProvider *query.IDPTemplate) (*gitlab.Provider, error) {
+ secret, err := crypto.DecryptString(identityProvider.GitLabIDPTemplate.ClientSecret, l.idpConfigAlg)
+ if err != nil {
+ return nil, err
+ }
+ return gitlab.New(
+ identityProvider.GitLabIDPTemplate.ClientID,
+ secret,
+ l.baseURL(ctx)+EndpointExternalLoginCallback,
+ identityProvider.GitLabIDPTemplate.Scopes,
+ )
+}
+
+func (l *Login) gitlabSelfHostedProvider(ctx context.Context, identityProvider *query.IDPTemplate) (*gitlab.Provider, error) {
+ secret, err := crypto.DecryptString(identityProvider.GitLabSelfHostedIDPTemplate.ClientSecret, l.idpConfigAlg)
+ if err != nil {
+ return nil, err
+ }
+ return gitlab.NewCustomIssuer(
+ identityProvider.Name,
+ identityProvider.GitLabSelfHostedIDPTemplate.Issuer,
+ identityProvider.GitLabSelfHostedIDPTemplate.ClientID,
+ secret,
+ l.baseURL(ctx)+EndpointExternalLoginCallback,
+ identityProvider.GitLabSelfHostedIDPTemplate.Scopes,
+ )
+}
+
func (l *Login) appendUserGrants(ctx context.Context, userGrants []*domain.UserGrant, resourceOwner string) error {
if len(userGrants) == 0 {
return nil
diff --git a/internal/api/ui/login/static/resources/images/idp/gitlab.png b/internal/api/ui/login/static/resources/images/idp/gitlab.png
new file mode 100644
index 0000000000..b4c82efed9
Binary files /dev/null and b/internal/api/ui/login/static/resources/images/idp/gitlab.png differ
diff --git a/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_base.scss b/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_base.scss
index b459308b69..074ebd3460 100644
--- a/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_base.scss
+++ b/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_base.scss
@@ -4,6 +4,7 @@ $lgn-idp-provider-name-line-height: 36px;
$lgn-idp-border-radius: .5rem;
$googlelogosource: '../../../images/idp/google';
$githublogosource: '../../../images/idp/github';
+$gitlablogosource: '../../../images/idp/gitlab';
@mixin lgn-idp-base {
display: block;
@@ -52,4 +53,16 @@ $githublogosource: '../../../images/idp/github';
border-radius: 5px;
}
}
+
+ &.gitlab {
+ span.logo {
+ height: 46px;
+ width: 46px;
+ background-image: url($gitlablogosource + '.png');
+ background-size: 100%;
+ background-position: center;
+ background-repeat: no-repeat;
+ border-radius: 5px;
+ }
+ }
}
diff --git a/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_theme.scss b/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_theme.scss
index 2c4c746228..0d29a038ce 100644
--- a/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_theme.scss
+++ b/internal/api/ui/login/static/resources/themes/scss/styles/identity_provider/identity_provider_theme.scss
@@ -26,6 +26,11 @@
color: var(--zitadel-color-github-text);
background-color: var(--zitadel-color-github-background);
}
+
+ &.gitlab {
+ color: var(--zitadel-color-gitlab-text);
+ background-color: var(--zitadel-color-gitlab-background);
+ }
}
.lgn-idp-providers {
diff --git a/internal/api/ui/login/static/resources/themes/scss/styles/vars.scss b/internal/api/ui/login/static/resources/themes/scss/styles/vars.scss
index 8f3582c38a..304ed8a4f7 100644
--- a/internal/api/ui/login/static/resources/themes/scss/styles/vars.scss
+++ b/internal/api/ui/login/static/resources/themes/scss/styles/vars.scss
@@ -115,6 +115,8 @@
--zitadel-color-google-background: #ffffff;
--zitadel-color-github-text: #8b8d8d;
--zitadel-color-github-background: #ffffff;
+ --zitadel-color-gitlab-text: #8b8d8d;
+ --zitadel-color-gitlab-background: #ffffff;
--zitadel-color-qr: var(--zitadel-color-black);
--zitadel-color-qr-background: var(--zitadel-color-white);
@@ -218,4 +220,6 @@
--zitadel-color-google-background: #ffffff;
--zitadel-color-github-text: #8b8d8d;
--zitadel-color-github-background: #ffffff;
+ --zitadel-color-gitlab-text: #8b8d8d;
+ --zitadel-color-gitlab-background: #ffffff;
}
diff --git a/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css b/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css
index bce99cadb6..acbae860e9 100644
--- a/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css
+++ b/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css
@@ -100,6 +100,8 @@
--zitadel-color-google-background: #ffffff;
--zitadel-color-github-text: #8b8d8d;
--zitadel-color-github-background: #ffffff;
+ --zitadel-color-gitlab-text: #8b8d8d;
+ --zitadel-color-gitlab-background: #ffffff;
--zitadel-color-qr: var(--zitadel-color-black);
--zitadel-color-qr-background: var(--zitadel-color-white);
}
@@ -188,6 +190,8 @@
--zitadel-color-google-background: #ffffff;
--zitadel-color-github-text: #8b8d8d;
--zitadel-color-github-background: #ffffff;
+ --zitadel-color-gitlab-text: #8b8d8d;
+ --zitadel-color-gitlab-background: #ffffff;
}
body {
@@ -572,6 +576,15 @@ a.sub-formfield-link {
background-repeat: no-repeat;
border-radius: 5px;
}
+.lgn-idp.gitlab span.logo {
+ height: 46px;
+ width: 46px;
+ background-image: url("../../../images/idp/gitlab.png");
+ background-size: 100%;
+ background-position: center;
+ background-repeat: no-repeat;
+ border-radius: 5px;
+}
.lgn-error {
display: flex;
@@ -1556,6 +1569,15 @@ a.sub-formfield-link {
background-repeat: no-repeat;
border-radius: 5px;
}
+.lgn-idp.gitlab span.logo {
+ height: 46px;
+ width: 46px;
+ background-image: url("../../../images/idp/gitlab.png");
+ background-size: 100%;
+ background-position: center;
+ background-repeat: no-repeat;
+ border-radius: 5px;
+}
.lgn-error {
display: flex;
@@ -3073,6 +3095,10 @@ ul li i.lgn-valid {
color: var(--zitadel-color-github-text);
background-color: var(--zitadel-color-github-background);
}
+.lgn-idp.gitlab {
+ color: var(--zitadel-color-gitlab-text);
+ background-color: var(--zitadel-color-gitlab-background);
+}
.lgn-idp-providers .lgn-idp-desc {
color: var(--zitadel-color-label);
diff --git a/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css.map b/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css.map
index 8619068f9c..c1bd90d0c0 100644
--- a/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css.map
+++ b/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css.map
@@ -1 +1 @@
-{"version":3,"sourceRoot":"","sources":["../../scss/styles/vars.scss","../../scss/main.scss","../../scss/styles/footer/footer.scss","../../scss/styles/header/header.scss","../../scss/styles/button/button.scss","../../scss/styles/button/button_base.scss","../../scss/styles/input/input.scss","../../scss/styles/input/input_base.scss","../../scss/styles/label/label.scss","../../scss/styles/label/label_base.scss","../../scss/styles/radio/radio_base.scss","../../scss/styles/radio/radio.scss","../../scss/styles/a/a.scss","../../scss/styles/identity_provider/identity_provider.scss","../../scss/styles/identity_provider/identity_provider_base.scss","../../scss/styles/error/error.scss","../../scss/styles/qrcode/qrcode.scss","../../scss/styles/container/container.scss","../../scss/styles/account_selection/account_selection.scss","../../scss/styles/avatar/avatar.scss","../../scss/styles/checkbox/checkbox.scss","../../scss/styles/checkbox/checkbox_base.scss","../../scss/styles/select/select.scss","../../scss/styles/select/select_base.scss","../../scss/styles/list/list_base.scss","../../scss/styles/typography/faces/ailerons_font_faces.scss","../../scss/styles/typography/faces/lato_font_faces.scss","../../scss/styles/typography/faces/roboto_font_faces.scss","../../scss/styles/typography/faces/raleway_font_faces.scss","../../scss/styles/typography/faces/pt_sans_font_faces.scss","../../scss/styles/success_label/success_label.scss","../../scss/styles/mfa/mfa.scss","../../scss/styles/mfa/mfa_base.scss","../../scss/styles/register/register.scss","../../scss/styles/animations.scss","../../scss/styles/typography/typography.scss","../../scss/styles/core/core.scss","../../scss/styles/header/header_theme.scss","../../scss/styles/button/button_theme.scss","../../scss/styles/elevation/elevation.scss","../../scss/styles/input/input_theme.scss","../../scss/styles/radio/radio_theme.scss","../../scss/styles/checkbox/checkbox_theme.scss","../../scss/styles/label/label_theme.scss","../../scss/styles/footer/footer_theme.scss","../../scss/styles/a/a_theme.scss","../../scss/styles/error/error_theme.scss","../../scss/styles/qrcode/qrcode_theme.scss","../../scss/styles/container/container_theme.scss","../../scss/styles/account_selection/account_selection_theme.scss","../../scss/styles/avatar/avatar_theme.scss","../../scss/styles/select/select_theme.scss","../../scss/styles/list/list_theme.scss","../../scss/styles/identity_provider/identity_provider_theme.scss","../../scss/styles/success_label/success_label_theme.scss","../../scss/styles/mfa/mfa_theme.scss"],"names":[],"mappings":";AAAA;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;AAAA;AAAA;EAIA;EAEA;EACA;EACA;EACA;AAAA;AAAA;EAGA;EACA;EACA;EACA;AAAA;AAAA;EAIA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EAEA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;AAAA;AAAA;EAIA;EAEA;EACA;EACA;EACA;AAAA;AAAA;EAGA;EACA;EACA;EACA;AAAA;AAAA;AAIA;EACA;EACA;EAEA;EACA;EACA;EACA;;;AC3NF;EACI;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;;AAIR;EACI;;;AAGJ;EACI;;;AChBJ;EACE;EACA;EACA;EACA,YAPc;EAQd;EACA;EACA,SATe;;AAWf;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EAnBF;IAoBI;IACA;IACA;IACA;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;AAEA;EALF;IAMI;;;AAIJ;EACE;EACA;EACA;;;AC3CN;EACE;EACA;EACA,QALkB;EAMlB,SAPmB;EAQnB;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;;ACjBJ;ECkBE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;;AAEA;EACE;;AAGF;EACE;;;AD3CJ;ECcE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;EAgBA;;AAdA;EACE;;AAGF;EACE;;;ADvCJ;EACE;EACA;EACA,OCCqB;EDArB;EACA;EACA,aCFqB;EDGrB,eCF8B;;ADI9B;EACE,aCJ0B;;;ADQ9B;EACE;EACA,SCf2B;EDgB3B,aCjB+B;;;ADoBjC;EACE;EACA,YC3B4B;;;AD+B5B;EACE;;;AEnCJ;AAAA;ECOI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADrBR;AAAA;ECCI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADhBR;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AEvBJ;ECGI;EACA,WANkB;EAOlB;EACA,QAPe;EAQf,aAPoB;;ADGtB;EACE;;;AEEJ;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;;AChBJ;EDqBE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA,QA9Ba;EA+Bb;EACA,SA7BsB;EA8BtB;EACA;EACA;EACA;EACA;EACA,WAzCkB;EA0ClB;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA,OArDW;EAsDX,QAtDW;EAuDX;EACA;;AAGF;EACE;EACA;EACA,OA7DmB;EA8DnB,QA9DmB;EA+DnB;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAOA;EACE;EACA;;AAGF;EACE;;AAKN;AAAA;AAAA;EAGE;;;AE7GJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;;ACTJ;ECMI;EACA,QATa;EAUb;EACA;EACA;EACA;EACA,SAbc;EAcd,eAZoB;EAapB;EACA;;AAEA;EACI;EACA;;AAGJ;EACI,aAvB4B;EAwB5B;EACA;EACA;;AAIA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;ACnDZ;EACI;EACA;EACA;;AACA;EACI;EACA;;;AAIR;EACI;;;ACXJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;;ACHR;EACE,WAPwB;EAQxB;EACA;EACA,eAN4B;EAO5B;;AAEA;EAPF;IAQI,YAXuB;;;;AAe3B;EACE;EACA;EACA,QAnBqB;EAoBrB,SArBsB;EAsBtB;EACA;;AAGE;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAMR;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAKN;EACE;;;AC7HF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;EACA;;;AC/DR;EACI,QAHc;EAId,OAJc;EAKd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;ACrBJ;ECCE;EACA;EACA;EACA,WANuB;EAOvB;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA,WA5BqB;EA6BrB;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACtDN;ECCE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;;ACfA;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAIR;EACI;EACA;;;ACpCR;EACI;EACA;;ACFJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC7DJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;ACzEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC9GJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;ACtBJ;EACE;EACA;;;ACFF;ECDE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;A9BlCR;EACE;EACA;EACA;EACA,YAPc;EAQd;EACA;EACA,SATe;;AAWf;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EAnBF;IAoBI;IACA;IACA;IACA;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;AAEA;EALF;IAMI;;;AAIJ;EACE;EACA;EACA;;;AC3CN;EACE;EACA;EACA,QALkB;EAMlB,SAPmB;EAQnB;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;;ACjBJ;ECkBE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;;AAEA;EACE;;AAGF;EACE;;;AD3CJ;ECcE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;EAgBA;;AAdA;EACE;;AAGF;EACE;;;ADvCJ;EACE;EACA;EACA,OCCqB;EDArB;EACA;EACA,aCFqB;EDGrB,eCF8B;;ADI9B;EACE,aCJ0B;;;ADQ9B;EACE;EACA,SCf2B;EDgB3B,aCjB+B;;;ADoBjC;EACE;EACA,YC3B4B;;;AD+B5B;EACE;;;AEnCJ;AAAA;ECOI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADrBR;AAAA;ECCI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADhBR;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AEvBJ;ECGI;EACA,WANkB;EAOlB;EACA,QAPe;EAQf,aAPoB;;ADGtB;EACE;;;AEEJ;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;;AChBJ;EDqBE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA,QA9Ba;EA+Bb;EACA,SA7BsB;EA8BtB;EACA;EACA;EACA;EACA;EACA,WAzCkB;EA0ClB;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA,OArDW;EAsDX,QAtDW;EAuDX;EACA;;AAGF;EACE;EACA;EACA,OA7DmB;EA8DnB,QA9DmB;EA+DnB;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAOA;EACE;EACA;;AAGF;EACE;;AAKN;AAAA;AAAA;EAGE;;;AE7GJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;;ACTJ;ECMI;EACA,QATa;EAUb;EACA;EACA;EACA;EACA,SAbc;EAcd,eAZoB;EAapB;EACA;;AAEA;EACI;EACA;;AAGJ;EACI,aAvB4B;EAwB5B;EACA;EACA;;AAIA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;ACnDZ;EACI;EACA;EACA;;AACA;EACI;EACA;;;AAIR;EACI;;;ACXJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;;ACHR;EACE,WAPwB;EAQxB;EACA;EACA,eAN4B;EAO5B;;AAEA;EAPF;IAQI,YAXuB;;;;AAe3B;EACE;EACA;EACA,QAnBqB;EAoBrB,SArBsB;EAsBtB;EACA;;AAGE;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAMR;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAKN;EACE;;;AC7HF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;EACA;;;AC/DR;EACI,QAHc;EAId,OAJc;EAKd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;ACrBJ;ECCE;EACA;EACA;EACA,WANuB;EAOvB;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA,WA5BqB;EA6BrB;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACtDN;ECCE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;;ACfA;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAIR;EACI;EACA;;;ACpCR;EACI;EACA;;ACFJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC7DJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;ACzEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC9GJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;ACtBJ;EACE;EACA;;;ACFF;ECDE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;APtCR;EACI;EACA;;ACFJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC7DJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;ACzEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC9GJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AZlBJ;EACE,WAPwB;EAQxB;EACA;EACA,eAN4B;EAO5B;;AAEA;EAPF;IAQI,YAXuB;;;;AAe3B;EACE;EACA;EACA,QAnBqB;EAoBrB,SArBsB;EAsBtB;EACA;;AAGE;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAMR;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAKN;EACE;;;AgB9HE;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAIR;EACI;;;A9BdR;EACE;EACA;EACA,QALkB;EAMlB,SAPmB;EAQnB;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;;A+BnBJ;EACI;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;;AAIN;EACI;EACA;;;ACqIA;EANE;EACA,aAlEY;EAGd;EAsEE;;;AAGF;EAXE;EACA,aAlEY;EAGd;EA2EE;;;AAGF;EAhBE;EACA,aAlEY;EAGd;EAgFE;;;AAGF;EArBE;EACA,aAlEY;EAGd;EAqFE;;;AAGF;EA1BE;EACA,aAlEY;EAGd;;;AA4FA;EA9BE;EACA,aAlEY;EAGd;;AA+FE;EACE;;;AAIJ;EAtCE;EACA,aAlEY;EAGd;;;AAwGA;EA1CE;EACA,aAlEY;EAGd;;;AA4GA;EA9CE;EACA,aAlEY;EAGd;;;AAgHA;EAlDE;EACA,aAlEY;EAGd;;;AAoHA;EAtDE;EACA,aAlEY;EAGd;EAsHI;;;AAGJ;EA3DE;EACA,aAlEY;EAGd;EA2HE;;;AAGF;EAhEE;EACA,aAlEY;EAGd;EAgIE;;;AAGF;EArEE;EACA,aAlEY;EAGd;EAqIE;;;AAGF;EA1EE;EACA,aAlEY;EAGd;EA0IE;;;ACvNF;EACE;EACA;;;AAKA;EACE;;;ACTJ;EACI;EACA;;;ACAN;AAAA;AAAA;EAGE;EACA;;AA0HF;AAAA;AAAA;EACE,OAPM;;AASR;AAAA;AAAA;EACE,OAVM;;AAYR;AAAA;AAAA;EACE,OAbM;;AAoBN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;;AApIJ;AAAA;EAEE;;;AAGF;EACE;;;AAGF;AAAA;EC2GA;EDxGE;;;AAGF;EACE;;;AAqGF;EACE,OAPM;;AASR;EACE,OAVM;;AAYR;EACE,OAbM;;AAoBN;EACE;;AA/GF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAIJ;EACE;EACA;;AAiFF;EACE,OAPM;;AASR;EACE,OAVM;;AAYR;EACE,OAbM;;AAoBN;EACE;;AAMJ;EACE;;AAEF;EACE;;AAEF;EACE;;AAOA;EACE;;AAhHF;EACE;;;AAIJ;AAAA;ECsEA;;;ADjEA;ECiEA;;AD9DE;EC8DF;;ADtDE;ECsDF;;;AC9HA;AAAA;AAAA;EAGE;;;AAGF;AAAA;AAAA;EAGE;EACA;;AAEA;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;EACE;;AAIF;AAAA;AAAA;EACE;;;AAIJ;AAAA;AAAA;EAGE;;;AChCI;EACI;;AAGJ;EACI;;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIA;EACI;;AAIA;EACI;;AAGJ;EACI;;AAIR;EACI;;;ACtCd;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAKA;EACE;EACA;;AAGF;EACE;EACA;EACA;;;AAMF;EACE;EACA;;AAGF;EACE;;;AC7BF;EACE;;;ACFJ;EACE;EACA;EACA;;AAEA;EALF;IAMI;IACA;;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;;ACpBJ;EACE;;AAEA;EAEE;;;ACJF;EACE;;;ACAE;EACI;;AAGJ;EACI;;AAGJ;EACI;;;ACTJ;EACI;;;AAKJ;EACI;;;ACTV;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;ACnBR;EACE,kBAPM;;AASR;EACE,kBAVM;;AAYR;EACE,kBAbM;;AAoBN;EAME,kBALY;;;AChCd;EACI;;;ACCJ;AAAA;EACE;;AAIA;AAAA;EACE;;AAGF;AAAA;EACE;;;ACbN;EACE;EACA;;AAEA;Ed2HF;;AcvHE;EduHF;;AcnHE;EACE;EACA;;AAGF;EACE;EACA;;;AAKF;EACE;;;ACxBJ;EACE;EACA;;;ACAQ;EACE;EACA;;AAKN;EACE;;AAGF;EACE;EACA;EACA","file":"zitadel.css"}
\ No newline at end of file
+{"version":3,"sourceRoot":"","sources":["../../scss/styles/vars.scss","../../scss/main.scss","../../scss/styles/footer/footer.scss","../../scss/styles/header/header.scss","../../scss/styles/button/button.scss","../../scss/styles/button/button_base.scss","../../scss/styles/input/input.scss","../../scss/styles/input/input_base.scss","../../scss/styles/label/label.scss","../../scss/styles/label/label_base.scss","../../scss/styles/radio/radio_base.scss","../../scss/styles/radio/radio.scss","../../scss/styles/a/a.scss","../../scss/styles/identity_provider/identity_provider.scss","../../scss/styles/identity_provider/identity_provider_base.scss","../../scss/styles/error/error.scss","../../scss/styles/qrcode/qrcode.scss","../../scss/styles/container/container.scss","../../scss/styles/account_selection/account_selection.scss","../../scss/styles/avatar/avatar.scss","../../scss/styles/checkbox/checkbox.scss","../../scss/styles/checkbox/checkbox_base.scss","../../scss/styles/select/select.scss","../../scss/styles/select/select_base.scss","../../scss/styles/list/list_base.scss","../../scss/styles/typography/faces/ailerons_font_faces.scss","../../scss/styles/typography/faces/lato_font_faces.scss","../../scss/styles/typography/faces/roboto_font_faces.scss","../../scss/styles/typography/faces/raleway_font_faces.scss","../../scss/styles/typography/faces/pt_sans_font_faces.scss","../../scss/styles/success_label/success_label.scss","../../scss/styles/mfa/mfa.scss","../../scss/styles/mfa/mfa_base.scss","../../scss/styles/register/register.scss","../../scss/styles/animations.scss","../../scss/styles/typography/typography.scss","../../scss/styles/core/core.scss","../../scss/styles/header/header_theme.scss","../../scss/styles/button/button_theme.scss","../../scss/styles/elevation/elevation.scss","../../scss/styles/input/input_theme.scss","../../scss/styles/radio/radio_theme.scss","../../scss/styles/checkbox/checkbox_theme.scss","../../scss/styles/label/label_theme.scss","../../scss/styles/footer/footer_theme.scss","../../scss/styles/a/a_theme.scss","../../scss/styles/error/error_theme.scss","../../scss/styles/qrcode/qrcode_theme.scss","../../scss/styles/container/container_theme.scss","../../scss/styles/account_selection/account_selection_theme.scss","../../scss/styles/avatar/avatar_theme.scss","../../scss/styles/select/select_theme.scss","../../scss/styles/list/list_theme.scss","../../scss/styles/identity_provider/identity_provider_theme.scss","../../scss/styles/success_label/success_label_theme.scss","../../scss/styles/mfa/mfa_theme.scss"],"names":[],"mappings":";AAAA;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;AAAA;AAAA;EAIA;EAEA;EACA;EACA;EACA;AAAA;AAAA;EAGA;EACA;EACA;EACA;AAAA;AAAA;EAIA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;AAAA;AAAA;EAIA;EAEA;EACA;EACA;EACA;AAAA;AAAA;EAGA;EACA;EACA;EACA;AAAA;AAAA;AAIA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;;AC/NF;EACI;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;;AAIR;EACI;;;AAGJ;EACI;;;AChBJ;EACE;EACA;EACA;EACA,YAPc;EAQd;EACA;EACA,SATe;;AAWf;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EAnBF;IAoBI;IACA;IACA;IACA;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;AAEA;EALF;IAMI;;;AAIJ;EACE;EACA;EACA;;;AC3CN;EACE;EACA;EACA,QALkB;EAMlB,SAPmB;EAQnB;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;;ACjBJ;ECkBE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;;AAEA;EACE;;AAGF;EACE;;;AD3CJ;ECcE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;EAgBA;;AAdA;EACE;;AAGF;EACE;;;ADvCJ;EACE;EACA;EACA,OCCqB;EDArB;EACA;EACA,aCFqB;EDGrB,eCF8B;;ADI9B;EACE,aCJ0B;;;ADQ9B;EACE;EACA,SCf2B;EDgB3B,aCjB+B;;;ADoBjC;EACE;EACA,YC3B4B;;;AD+B5B;EACE;;;AEnCJ;AAAA;ECOI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADrBR;AAAA;ECCI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADhBR;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AEvBJ;ECGI;EACA,WANkB;EAOlB;EACA,QAPe;EAQf,aAPoB;;ADGtB;EACE;;;AEEJ;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;;AChBJ;EDqBE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA,QA9Ba;EA+Bb;EACA,SA7BsB;EA8BtB;EACA;EACA;EACA;EACA;EACA,WAzCkB;EA0ClB;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA,OArDW;EAsDX,QAtDW;EAuDX;EACA;;AAGF;EACE;EACA;EACA,OA7DmB;EA8DnB,QA9DmB;EA+DnB;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAOA;EACE;EACA;;AAGF;EACE;;AAKN;AAAA;AAAA;EAGE;;;AE7GJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;;ACTJ;ECOI;EACA,QAVa;EAWb;EACA;EACA;EACA;EACA,SAdc;EAed,eAboB;EAcpB;EACA;;AAEA;EACI;EACA;;AAGJ;EACI,aAxB4B;EAyB5B;EACA;EACA;;AAIA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AChEZ;EACI;EACA;EACA;;AACA;EACI;EACA;;;AAIR;EACI;;;ACXJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;;ACHR;EACE,WAPwB;EAQxB;EACA;EACA,eAN4B;EAO5B;;AAEA;EAPF;IAQI,YAXuB;;;;AAe3B;EACE;EACA;EACA,QAnBqB;EAoBrB,SArBsB;EAsBtB;EACA;;AAGE;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAMR;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAKN;EACE;;;AC7HF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;EACA;;;AC/DR;EACI,QAHc;EAId,OAJc;EAKd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;ACrBJ;ECCE;EACA;EACA;EACA,WANuB;EAOvB;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA,WA5BqB;EA6BrB;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACtDN;ECCE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;;ACfA;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAIR;EACI;EACA;;;ACpCR;EACI;EACA;;ACFJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC7DJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;ACzEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC9GJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;ACtBJ;EACE;EACA;;;ACFF;ECDE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;A9BlCR;EACE;EACA;EACA;EACA,YAPc;EAQd;EACA;EACA,SATe;;AAWf;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EAnBF;IAoBI;IACA;IACA;IACA;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;AAEA;EALF;IAMI;;;AAIJ;EACE;EACA;EACA;;;AC3CN;EACE;EACA;EACA,QALkB;EAMlB,SAPmB;EAQnB;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;;ACjBJ;ECkBE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;;AAEA;EACE;;AAGF;EACE;;;AD3CJ;ECcE;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA,QAjCkB;EAkClB,WAnCqB;EAoCrB,aAlCuB;EAmCvB,SAtCmB;EAuCnB,eAnCyB;EAqCzB;EACA;EAgBA;;AAdA;EACE;;AAGF;EACE;;;ADvCJ;EACE;EACA;EACA,OCCqB;EDArB;EACA;EACA,aCFqB;EDGrB,eCF8B;;ADI9B;EACE,aCJ0B;;;ADQ9B;EACE;EACA,SCf2B;EDgB3B,aCjB+B;;;ADoBjC;EACE;EACA,YC3B4B;;;AD+B5B;EACE;;;AEnCJ;AAAA;ECOI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADrBR;AAAA;ECCI;EACA;EACA,sBAXsB;EAYtB;EACA;EACA;EACA;EACA,eAZsB;EAatB;EACA;EACA;EACA,cAfqB;EAgBrB,QAlBoB;EAmBpB,SArBgB;EAsBhB;EACA;EACA,QAvBe;;AAyBf;AAAA;EACI,WAtB0B;EAuB1B;;;ADhBR;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AEvBJ;ECGI;EACA,WANkB;EAOlB;EACA,QAPe;EAQf,aAPoB;;ADGtB;EACE;;;AEEJ;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;;AChBJ;EDqBE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA,QA9Ba;EA+Bb;EACA,SA7BsB;EA8BtB;EACA;EACA;EACA;EACA;EACA,WAzCkB;EA0ClB;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA,OArDW;EAsDX,QAtDW;EAuDX;EACA;;AAGF;EACE;EACA;EACA,OA7DmB;EA8DnB,QA9DmB;EA+DnB;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAOA;EACE;EACA;;AAGF;EACE;;AAKN;AAAA;AAAA;EAGE;;;AE7GJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;;ACTJ;ECOI;EACA,QAVa;EAWb;EACA;EACA;EACA;EACA,SAdc;EAed,eAboB;EAcpB;EACA;;AAEA;EACI;EACA;;AAGJ;EACI,aAxB4B;EAyB5B;EACA;EACA;;AAIA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AChEZ;EACI;EACA;EACA;;AACA;EACI;EACA;;;AAIR;EACI;;;ACXJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;;ACHR;EACE,WAPwB;EAQxB;EACA;EACA,eAN4B;EAO5B;;AAEA;EAPF;IAQI,YAXuB;;;;AAe3B;EACE;EACA;EACA,QAnBqB;EAoBrB,SArBsB;EAsBtB;EACA;;AAGE;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAMR;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAKN;EACE;;;AC7HF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;EACA;;;AC/DR;EACI,QAHc;EAId,OAJc;EAKd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;ACrBJ;ECCE;EACA;EACA;EACA,WANuB;EAOvB;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA,WA5BqB;EA6BrB;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACtDN;ECCE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;;ACfA;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAIR;EACI;EACA;;;ACpCR;EACI;EACA;;ACFJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC7DJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;ACzEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC9GJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;ACtBJ;EACE;EACA;;;ACFF;ECDE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;APtCR;EACI;EACA;;ACFJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC7DJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;ACzEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AC9GJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AZlBJ;EACE,WAPwB;EAQxB;EACA;EACA,eAN4B;EAO5B;;AAEA;EAPF;IAQI,YAXuB;;;;AAe3B;EACE;EACA;EACA,QAnBqB;EAoBrB,SArBsB;EAsBtB;EACA;;AAGE;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;;AAMR;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAKN;EACE;;;AgB9HE;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAIR;EACI;;;A9BdR;EACE;EACA;EACA,QALkB;EAMlB,SAPmB;EAQnB;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;;A+BnBJ;EACI;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;;AAIN;EACI;EACA;;;ACqIA;EANE;EACA,aAlEY;EAGd;EAsEE;;;AAGF;EAXE;EACA,aAlEY;EAGd;EA2EE;;;AAGF;EAhBE;EACA,aAlEY;EAGd;EAgFE;;;AAGF;EArBE;EACA,aAlEY;EAGd;EAqFE;;;AAGF;EA1BE;EACA,aAlEY;EAGd;;;AA4FA;EA9BE;EACA,aAlEY;EAGd;;AA+FE;EACE;;;AAIJ;EAtCE;EACA,aAlEY;EAGd;;;AAwGA;EA1CE;EACA,aAlEY;EAGd;;;AA4GA;EA9CE;EACA,aAlEY;EAGd;;;AAgHA;EAlDE;EACA,aAlEY;EAGd;;;AAoHA;EAtDE;EACA,aAlEY;EAGd;EAsHI;;;AAGJ;EA3DE;EACA,aAlEY;EAGd;EA2HE;;;AAGF;EAhEE;EACA,aAlEY;EAGd;EAgIE;;;AAGF;EArEE;EACA,aAlEY;EAGd;EAqIE;;;AAGF;EA1EE;EACA,aAlEY;EAGd;EA0IE;;;ACvNF;EACE;EACA;;;AAKA;EACE;;;ACTJ;EACI;EACA;;;ACAN;AAAA;AAAA;EAGE;EACA;;AA0HF;AAAA;AAAA;EACE,OAPM;;AASR;AAAA;AAAA;EACE,OAVM;;AAYR;AAAA;AAAA;EACE,OAbM;;AAoBN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;;AApIJ;AAAA;EAEE;;;AAGF;EACE;;;AAGF;AAAA;EC2GA;EDxGE;;;AAGF;EACE;;;AAqGF;EACE,OAPM;;AASR;EACE,OAVM;;AAYR;EACE,OAbM;;AAoBN;EACE;;AA/GF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAIJ;EACE;EACA;;AAiFF;EACE,OAPM;;AASR;EACE,OAVM;;AAYR;EACE,OAbM;;AAoBN;EACE;;AAMJ;EACE;;AAEF;EACE;;AAEF;EACE;;AAOA;EACE;;AAhHF;EACE;;;AAIJ;AAAA;ECsEA;;;ADjEA;ECiEA;;AD9DE;EC8DF;;ADtDE;ECsDF;;;AC9HA;AAAA;AAAA;EAGE;;;AAGF;AAAA;AAAA;EAGE;EACA;;AAEA;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;EACE;;AAIF;AAAA;AAAA;EACE;;;AAIJ;AAAA;AAAA;EAGE;;;AChCI;EACI;;AAGJ;EACI;;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIA;EACI;;AAIA;EACI;;AAGJ;EACI;;AAIR;EACI;;;ACtCd;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAKA;EACE;EACA;;AAGF;EACE;EACA;EACA;;;AAMF;EACE;EACA;;AAGF;EACE;;;AC7BF;EACE;;;ACFJ;EACE;EACA;EACA;;AAEA;EALF;IAMI;IACA;;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;;ACpBJ;EACE;;AAEA;EAEE;;;ACJF;EACE;;;ACAE;EACI;;AAGJ;EACI;;AAGJ;EACI;;;ACTJ;EACI;;;AAKJ;EACI;;;ACTV;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;ACnBR;EACE,kBAPM;;AASR;EACE,kBAVM;;AAYR;EACE,kBAbM;;AAoBN;EAME,kBALY;;;AChCd;EACI;;;ACCJ;AAAA;EACE;;AAIA;AAAA;EACE;;AAGF;AAAA;EACE;;;ACbN;EACE;EACA;;AAEA;Ed2HF;;AcvHE;EduHF;;AcnHE;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAKF;EACE;;;AC7BJ;EACE;EACA;;;ACAQ;EACE;EACA;;AAKN;EACE;;AAGF;EACE;EACA;EACA","file":"zitadel.css"}
diff --git a/internal/api/ui/login/static/templates/login.html b/internal/api/ui/login/static/templates/login.html
index c811e001cb..33c81a005e 100644
--- a/internal/api/ui/login/static/templates/login.html
+++ b/internal/api/ui/login/static/templates/login.html
@@ -49,7 +49,7 @@
- {{$provider.Name}}
+ {{$provider.DisplayName}}
{{end}}
diff --git a/internal/api/ui/login/static/templates/register_option.html b/internal/api/ui/login/static/templates/register_option.html
index 8ff122d9e0..24de130a33 100644
--- a/internal/api/ui/login/static/templates/register_option.html
+++ b/internal/api/ui/login/static/templates/register_option.html
@@ -29,7 +29,7 @@
- {{$provider.Name}}
+ {{$provider.DisplayName}}
{{end}}
{{end}}
diff --git a/internal/command/idp.go b/internal/command/idp.go
index 360ca6a9af..660d0cc7c3 100644
--- a/internal/command/idp.go
+++ b/internal/command/idp.go
@@ -57,6 +57,23 @@ type GitHubEnterpriseProvider struct {
IDPOptions idp.Options
}
+type GitLabProvider struct {
+ Name string
+ ClientID string
+ ClientSecret string
+ Scopes []string
+ IDPOptions idp.Options
+}
+
+type GitLabSelfHostedProvider struct {
+ Name string
+ Issuer string
+ ClientID string
+ ClientSecret string
+ Scopes []string
+ IDPOptions idp.Options
+}
+
type GoogleProvider struct {
Name string
ClientID string
diff --git a/internal/command/idp_model.go b/internal/command/idp_model.go
index 4d253abb94..147df0291a 100644
--- a/internal/command/idp_model.go
+++ b/internal/command/idp_model.go
@@ -613,6 +613,188 @@ func (wm *GitHubEnterpriseIDPWriteModel) NewChanges(
return changes, nil
}
+type GitLabIDPWriteModel struct {
+ eventstore.WriteModel
+
+ ID string
+ Name string
+ ClientID string
+ ClientSecret *crypto.CryptoValue
+ Scopes []string
+ idp.Options
+
+ State domain.IDPState
+}
+
+func (wm *GitLabIDPWriteModel) Reduce() error {
+ for _, event := range wm.Events {
+ switch e := event.(type) {
+ case *idp.GitLabIDPAddedEvent:
+ wm.reduceAddedEvent(e)
+ case *idp.GitLabIDPChangedEvent:
+ wm.reduceChangedEvent(e)
+ case *idp.RemovedEvent:
+ wm.State = domain.IDPStateRemoved
+ }
+ }
+ return wm.WriteModel.Reduce()
+}
+
+func (wm *GitLabIDPWriteModel) reduceAddedEvent(e *idp.GitLabIDPAddedEvent) {
+ wm.Name = e.Name
+ wm.ClientID = e.ClientID
+ wm.ClientSecret = e.ClientSecret
+ wm.Scopes = e.Scopes
+ wm.Options = e.Options
+ wm.State = domain.IDPStateActive
+}
+
+func (wm *GitLabIDPWriteModel) reduceChangedEvent(e *idp.GitLabIDPChangedEvent) {
+ if e.Name != nil {
+ wm.Name = *e.Name
+ }
+ if e.ClientID != nil {
+ wm.ClientID = *e.ClientID
+ }
+ if e.ClientSecret != nil {
+ wm.ClientSecret = e.ClientSecret
+ }
+ if e.Scopes != nil {
+ wm.Scopes = e.Scopes
+ }
+ wm.Options.ReduceChanges(e.OptionChanges)
+}
+
+func (wm *GitLabIDPWriteModel) NewChanges(
+ name,
+ clientID,
+ clientSecretString string,
+ secretCrypto crypto.Crypto,
+ scopes []string,
+ options idp.Options,
+) ([]idp.GitLabIDPChanges, error) {
+ changes := make([]idp.GitLabIDPChanges, 0)
+ var clientSecret *crypto.CryptoValue
+ var err error
+ if clientSecretString != "" {
+ clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
+ if err != nil {
+ return nil, err
+ }
+ changes = append(changes, idp.ChangeGitLabClientSecret(clientSecret))
+ }
+ if wm.Name != name {
+ changes = append(changes, idp.ChangeGitLabName(name))
+ }
+ if wm.ClientID != clientID {
+ changes = append(changes, idp.ChangeGitLabClientID(clientID))
+ }
+ if !reflect.DeepEqual(wm.Scopes, scopes) {
+ changes = append(changes, idp.ChangeGitLabScopes(scopes))
+ }
+
+ opts := wm.Options.Changes(options)
+ if !opts.IsZero() {
+ changes = append(changes, idp.ChangeGitLabOptions(opts))
+ }
+ return changes, nil
+}
+
+type GitLabSelfHostedIDPWriteModel struct {
+ eventstore.WriteModel
+
+ ID string
+ Name string
+ Issuer string
+ ClientID string
+ ClientSecret *crypto.CryptoValue
+ Scopes []string
+ idp.Options
+
+ State domain.IDPState
+}
+
+func (wm *GitLabSelfHostedIDPWriteModel) Reduce() error {
+ for _, event := range wm.Events {
+ switch e := event.(type) {
+ case *idp.GitLabSelfHostedIDPAddedEvent:
+ wm.reduceAddedEvent(e)
+ case *idp.GitLabSelfHostedIDPChangedEvent:
+ wm.reduceChangedEvent(e)
+ case *idp.RemovedEvent:
+ wm.State = domain.IDPStateRemoved
+ }
+ }
+ return wm.WriteModel.Reduce()
+}
+
+func (wm *GitLabSelfHostedIDPWriteModel) reduceAddedEvent(e *idp.GitLabSelfHostedIDPAddedEvent) {
+ wm.Name = e.Name
+ wm.Issuer = e.Issuer
+ wm.ClientID = e.ClientID
+ wm.ClientSecret = e.ClientSecret
+ wm.Scopes = e.Scopes
+ wm.Options = e.Options
+ wm.State = domain.IDPStateActive
+}
+
+func (wm *GitLabSelfHostedIDPWriteModel) reduceChangedEvent(e *idp.GitLabSelfHostedIDPChangedEvent) {
+ if e.ClientID != nil {
+ wm.ClientID = *e.ClientID
+ }
+ if e.ClientSecret != nil {
+ wm.ClientSecret = e.ClientSecret
+ }
+ if e.Name != nil {
+ wm.Name = *e.Name
+ }
+ if e.Issuer != nil {
+ wm.Issuer = *e.Issuer
+ }
+ if e.Scopes != nil {
+ wm.Scopes = e.Scopes
+ }
+ wm.Options.ReduceChanges(e.OptionChanges)
+}
+
+func (wm *GitLabSelfHostedIDPWriteModel) NewChanges(
+ name string,
+ issuer string,
+ clientID string,
+ clientSecretString string,
+ secretCrypto crypto.Crypto,
+ scopes []string,
+ options idp.Options,
+) ([]idp.GitLabSelfHostedIDPChanges, error) {
+ changes := make([]idp.GitLabSelfHostedIDPChanges, 0)
+ var clientSecret *crypto.CryptoValue
+ var err error
+ if clientSecretString != "" {
+ clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
+ if err != nil {
+ return nil, err
+ }
+ changes = append(changes, idp.ChangeGitLabSelfHostedClientSecret(clientSecret))
+ }
+ if wm.ClientID != clientID {
+ changes = append(changes, idp.ChangeGitLabSelfHostedClientID(clientID))
+ }
+ if wm.Name != name {
+ changes = append(changes, idp.ChangeGitLabSelfHostedName(name))
+ }
+ if wm.Issuer != issuer {
+ changes = append(changes, idp.ChangeGitLabSelfHostedIssuer(issuer))
+ }
+ if !reflect.DeepEqual(wm.Scopes, scopes) {
+ changes = append(changes, idp.ChangeGitLabSelfHostedScopes(scopes))
+ }
+ opts := wm.Options.Changes(options)
+ if !opts.IsZero() {
+ changes = append(changes, idp.ChangeGitLabSelfHostedOptions(opts))
+ }
+ return changes, nil
+}
+
type GoogleIDPWriteModel struct {
eventstore.WriteModel
@@ -871,6 +1053,10 @@ func (wm *IDPRemoveWriteModel) Reduce() error {
wm.reduceAdded(e.ID)
case *idp.GitHubEnterpriseIDPAddedEvent:
wm.reduceAdded(e.ID)
+ case *idp.GitLabIDPAddedEvent:
+ wm.reduceAdded(e.ID)
+ case *idp.GitLabSelfHostedIDPAddedEvent:
+ wm.reduceAdded(e.ID)
case *idp.GoogleIDPAddedEvent:
wm.reduceAdded(e.ID)
case *idp.LDAPIDPAddedEvent:
diff --git a/internal/command/instance_idp.go b/internal/command/instance_idp.go
index 15c38a8f25..422ca44215 100644
--- a/internal/command/instance_idp.go
+++ b/internal/command/instance_idp.go
@@ -223,6 +223,90 @@ func (c *Commands) UpdateInstanceGitHubEnterpriseProvider(ctx context.Context, i
return pushedEventsToObjectDetails(pushedEvents), nil
}
+func (c *Commands) AddInstanceGitLabProvider(ctx context.Context, provider GitLabProvider) (string, *domain.ObjectDetails, error) {
+ instanceID := authz.GetInstance(ctx).InstanceID()
+ instanceAgg := instance.NewAggregate(instanceID)
+ id, err := c.idGenerator.Next()
+ if err != nil {
+ return "", nil, err
+ }
+ writeModel := NewGitLabInstanceIDPWriteModel(instanceID, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceGitLabProvider(instanceAgg, writeModel, provider))
+ if err != nil {
+ return "", nil, err
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return "", nil, err
+ }
+ return id, pushedEventsToObjectDetails(pushedEvents), nil
+}
+
+func (c *Commands) UpdateInstanceGitLabProvider(ctx context.Context, id string, provider GitLabProvider) (*domain.ObjectDetails, error) {
+ instanceID := authz.GetInstance(ctx).InstanceID()
+ instanceAgg := instance.NewAggregate(instanceID)
+ writeModel := NewGitLabInstanceIDPWriteModel(instanceID, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceGitLabProvider(instanceAgg, writeModel, provider))
+ if err != nil {
+ return nil, err
+ }
+ if len(cmds) == 0 {
+ // no change, so return directly
+ return &domain.ObjectDetails{
+ Sequence: writeModel.ProcessedSequence,
+ EventDate: writeModel.ChangeDate,
+ ResourceOwner: writeModel.ResourceOwner,
+ }, nil
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return nil, err
+ }
+ return pushedEventsToObjectDetails(pushedEvents), nil
+}
+
+func (c *Commands) AddInstanceGitLabSelfHostedProvider(ctx context.Context, provider GitLabSelfHostedProvider) (string, *domain.ObjectDetails, error) {
+ instanceID := authz.GetInstance(ctx).InstanceID()
+ instanceAgg := instance.NewAggregate(instanceID)
+ id, err := c.idGenerator.Next()
+ if err != nil {
+ return "", nil, err
+ }
+ writeModel := NewGitLabSelfHostedInstanceIDPWriteModel(instanceID, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceGitLabSelfHostedProvider(instanceAgg, writeModel, provider))
+ if err != nil {
+ return "", nil, err
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return "", nil, err
+ }
+ return id, pushedEventsToObjectDetails(pushedEvents), nil
+}
+
+func (c *Commands) UpdateInstanceGitLabSelfHostedProvider(ctx context.Context, id string, provider GitLabSelfHostedProvider) (*domain.ObjectDetails, error) {
+ instanceID := authz.GetInstance(ctx).InstanceID()
+ instanceAgg := instance.NewAggregate(instanceID)
+ writeModel := NewGitLabSelfHostedInstanceIDPWriteModel(instanceID, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceGitLabSelfHostedProvider(instanceAgg, writeModel, provider))
+ if err != nil {
+ return nil, err
+ }
+ if len(cmds) == 0 {
+ // no change, so return directly
+ return &domain.ObjectDetails{
+ Sequence: writeModel.ProcessedSequence,
+ EventDate: writeModel.ChangeDate,
+ ResourceOwner: writeModel.ResourceOwner,
+ }, nil
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return nil, err
+ }
+ return pushedEventsToObjectDetails(pushedEvents), nil
+}
+
func (c *Commands) AddInstanceGoogleProvider(ctx context.Context, provider GoogleProvider) (string, *domain.ObjectDetails, error) {
instanceID := authz.GetInstance(ctx).InstanceID()
instanceAgg := instance.NewAggregate(instanceID)
@@ -395,23 +479,26 @@ func (c *Commands) prepareAddInstanceOAuthProvider(a *instance.Aggregate, writeM
func (c *Commands) prepareUpdateInstanceOAuthProvider(a *instance.Aggregate, writeModel *InstanceOAuthIDPWriteModel, provider GenericOAuthProvider) preparation.Validation {
return func() (preparation.CreateCommands, error) {
+ if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SAffg", "Errors.Invalid.Argument")
+ }
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
- return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D32ef", "Errors.Invalid.Argument")
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Sf3gh", "Errors.Invalid.Argument")
}
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
- return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Dbgzf", "Errors.Invalid.Argument")
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SHJ3ui", "Errors.Invalid.Argument")
}
if provider.AuthorizationEndpoint = strings.TrimSpace(provider.AuthorizationEndpoint); provider.AuthorizationEndpoint == "" {
- return nil, caos_errs.ThrowInvalidArgument(nil, "INST-B23bs", "Errors.Invalid.Argument")
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SVrgh", "Errors.Invalid.Argument")
}
if provider.TokenEndpoint = strings.TrimSpace(provider.TokenEndpoint); provider.TokenEndpoint == "" {
- return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D2gj8", "Errors.Invalid.Argument")
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-DJKeio", "Errors.Invalid.Argument")
}
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
- return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Fb8jk", "Errors.Invalid.Argument")
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-ILSJi", "Errors.Invalid.Argument")
}
if provider.IDAttribute = strings.TrimSpace(provider.IDAttribute); provider.IDAttribute == "" {
- return nil, caos_errs.ThrowInvalidArgument(nil, "INST-asf3fs", "Errors.Invalid.Argument")
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-JKD3h", "Errors.Invalid.Argument")
}
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
events, err := filter(ctx, writeModel.Query())
@@ -700,12 +787,9 @@ func (c *Commands) prepareUpdateInstanceGitHubProvider(a *instance.Aggregate, wr
provider.Scopes,
provider.IDPOptions,
)
- if err != nil {
+ if err != nil || event == nil {
return nil, err
}
- if event == nil {
- return nil, nil
- }
return []eventstore.Command{event}, nil
}, nil
}
@@ -809,11 +893,174 @@ func (c *Commands) prepareUpdateInstanceGitHubEnterpriseProvider(a *instance.Agg
provider.Scopes,
provider.IDPOptions,
)
+ if err != nil || event == nil {
+ return nil, err
+ }
+ return []eventstore.Command{event}, nil
+ }, nil
+ }
+}
+
+func (c *Commands) prepareAddInstanceGitLabProvider(a *instance.Aggregate, writeModel *InstanceGitLabIDPWriteModel, provider GitLabProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-adsg2", "Errors.Invalid.Argument")
+ }
+ if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-GD1j2", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
if err != nil {
return nil, err
}
- if event == nil {
- return nil, nil
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ secret, err := crypto.Encrypt([]byte(provider.ClientSecret), c.idpConfigEncryption)
+ if err != nil {
+ return nil, err
+ }
+ return []eventstore.Command{
+ instance.NewGitLabIDPAddedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.ClientID,
+ secret,
+ provider.Scopes,
+ provider.IDPOptions,
+ ),
+ }, nil
+ }, nil
+ }
+}
+
+func (c *Commands) prepareUpdateInstanceGitLabProvider(a *instance.Aggregate, writeModel *InstanceGitLabIDPWriteModel, provider GitLabProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-HJK91", "Errors.Invalid.Argument")
+ }
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D12t6", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
+ if err != nil {
+ return nil, err
+ }
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ if !writeModel.State.Exists() {
+ return nil, caos_errs.ThrowNotFound(nil, "INST-HBReq", "Errors.Instance.IDPConfig.NotExisting")
+ }
+ event, err := writeModel.NewChangedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.ClientID,
+ provider.ClientSecret,
+ c.idpConfigEncryption,
+ provider.Scopes,
+ provider.IDPOptions,
+ )
+ if err != nil || event == nil {
+ return nil, err
+ }
+ return []eventstore.Command{event}, nil
+ }, nil
+ }
+}
+
+func (c *Commands) prepareAddInstanceGitLabSelfHostedProvider(a *instance.Aggregate, writeModel *InstanceGitLabSelfHostedIDPWriteModel, provider GitLabSelfHostedProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-jw4ZT", "Errors.Invalid.Argument")
+ }
+ if provider.Issuer = strings.TrimSpace(provider.Issuer); provider.Issuer == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-AST4S", "Errors.Invalid.Argument")
+ }
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-DBZHJ", "Errors.Invalid.Argument")
+ }
+ if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SDGJ4", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
+ if err != nil {
+ return nil, err
+ }
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ secret, err := crypto.Encrypt([]byte(provider.ClientSecret), c.idpConfigEncryption)
+ if err != nil {
+ return nil, err
+ }
+ return []eventstore.Command{
+ instance.NewGitLabSelfHostedIDPAddedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.Issuer,
+ provider.ClientID,
+ secret,
+ provider.Scopes,
+ provider.IDPOptions,
+ ),
+ }, nil
+ }, nil
+ }
+}
+
+func (c *Commands) prepareUpdateInstanceGitLabSelfHostedProvider(a *instance.Aggregate, writeModel *InstanceGitLabSelfHostedIDPWriteModel, provider GitLabSelfHostedProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SAFG4", "Errors.Invalid.Argument")
+ }
+ if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-DG4H", "Errors.Invalid.Argument")
+ }
+ if provider.Issuer = strings.TrimSpace(provider.Issuer); provider.Issuer == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SD4eb", "Errors.Invalid.Argument")
+ }
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "INST-GHWE3", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
+ if err != nil {
+ return nil, err
+ }
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ if !writeModel.State.Exists() {
+ return nil, caos_errs.ThrowNotFound(nil, "INST-D2tg1", "Errors.Instance.IDPConfig.NotExisting")
+ }
+ event, err := writeModel.NewChangedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.Issuer,
+ provider.ClientID,
+ provider.ClientSecret,
+ c.idpConfigEncryption,
+ provider.Scopes,
+ provider.IDPOptions,
+ )
+ if err != nil || event == nil {
+ return nil, err
}
return []eventstore.Command{event}, nil
}, nil
diff --git a/internal/command/instance_idp_model.go b/internal/command/instance_idp_model.go
index e18d6ee9f1..d8eb93eb83 100644
--- a/internal/command/instance_idp_model.go
+++ b/internal/command/instance_idp_model.go
@@ -25,10 +25,6 @@ func NewOAuthInstanceIDPWriteModel(instanceID, id string) *InstanceOAuthIDPWrite
}
}
-func (wm *InstanceOAuthIDPWriteModel) Reduce() error {
- return wm.OAuthIDPWriteModel.Reduce()
-}
-
func (wm *InstanceOAuthIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -107,10 +103,6 @@ func NewOIDCInstanceIDPWriteModel(instanceID, id string) *InstanceOIDCIDPWriteMo
}
}
-func (wm *InstanceOIDCIDPWriteModel) Reduce() error {
- return wm.OIDCIDPWriteModel.Reduce()
-}
-
func (wm *InstanceOIDCIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -208,10 +200,6 @@ func NewJWTInstanceIDPWriteModel(instanceID, id string) *InstanceJWTIDPWriteMode
}
}
-func (wm *InstanceJWTIDPWriteModel) Reduce() error {
- return wm.JWTIDPWriteModel.Reduce()
-}
-
func (wm *InstanceJWTIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -307,10 +295,6 @@ func NewGitHubInstanceIDPWriteModel(instanceID, id string) *InstanceGitHubIDPWri
}
}
-func (wm *InstanceGitHubIDPWriteModel) Reduce() error {
- return wm.GitHubIDPWriteModel.Reduce()
-}
-
func (wm *InstanceGitHubIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -376,10 +360,6 @@ func NewGitHubEnterpriseInstanceIDPWriteModel(instanceID, id string) *InstanceGi
}
}
-func (wm *InstanceGitHubEnterpriseIDPWriteModel) Reduce() error {
- return wm.GitHubEnterpriseIDPWriteModel.Reduce()
-}
-
func (wm *InstanceGitHubEnterpriseIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -442,6 +422,137 @@ func (wm *InstanceGitHubEnterpriseIDPWriteModel) NewChangedEvent(
return instance.NewGitHubEnterpriseIDPChangedEvent(ctx, aggregate, id, changes)
}
+type InstanceGitLabIDPWriteModel struct {
+ GitLabIDPWriteModel
+}
+
+func NewGitLabInstanceIDPWriteModel(instanceID, id string) *InstanceGitLabIDPWriteModel {
+ return &InstanceGitLabIDPWriteModel{
+ GitLabIDPWriteModel{
+ WriteModel: eventstore.WriteModel{
+ AggregateID: instanceID,
+ ResourceOwner: instanceID,
+ },
+ ID: id,
+ },
+ }
+}
+
+func (wm *InstanceGitLabIDPWriteModel) AppendEvents(events ...eventstore.Event) {
+ for _, event := range events {
+ switch e := event.(type) {
+ case *instance.GitLabIDPAddedEvent:
+ wm.GitLabIDPWriteModel.AppendEvents(&e.GitLabIDPAddedEvent)
+ case *instance.GitLabIDPChangedEvent:
+ wm.GitLabIDPWriteModel.AppendEvents(&e.GitLabIDPChangedEvent)
+ case *instance.IDPRemovedEvent:
+ wm.GitLabIDPWriteModel.AppendEvents(&e.RemovedEvent)
+ default:
+ wm.GitLabIDPWriteModel.AppendEvents(e)
+ }
+ }
+}
+
+func (wm *InstanceGitLabIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
+ return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
+ ResourceOwner(wm.ResourceOwner).
+ AddQuery().
+ AggregateTypes(instance.AggregateType).
+ AggregateIDs(wm.AggregateID).
+ EventTypes(
+ instance.GitLabIDPAddedEventType,
+ instance.GitLabIDPChangedEventType,
+ instance.IDPRemovedEventType,
+ ).
+ EventData(map[string]interface{}{"id": wm.ID}).
+ Builder()
+}
+
+func (wm *InstanceGitLabIDPWriteModel) NewChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ clientID string,
+ clientSecretString string,
+ secretCrypto crypto.Crypto,
+ scopes []string,
+ options idp.Options,
+) (*instance.GitLabIDPChangedEvent, error) {
+
+ changes, err := wm.GitLabIDPWriteModel.NewChanges(name, clientID, clientSecretString, secretCrypto, scopes, options)
+ if err != nil || len(changes) == 0 {
+ return nil, err
+ }
+ return instance.NewGitLabIDPChangedEvent(ctx, aggregate, id, changes)
+}
+
+type InstanceGitLabSelfHostedIDPWriteModel struct {
+ GitLabSelfHostedIDPWriteModel
+}
+
+func NewGitLabSelfHostedInstanceIDPWriteModel(instanceID, id string) *InstanceGitLabSelfHostedIDPWriteModel {
+ return &InstanceGitLabSelfHostedIDPWriteModel{
+ GitLabSelfHostedIDPWriteModel{
+ WriteModel: eventstore.WriteModel{
+ AggregateID: instanceID,
+ ResourceOwner: instanceID,
+ },
+ ID: id,
+ },
+ }
+}
+
+func (wm *InstanceGitLabSelfHostedIDPWriteModel) AppendEvents(events ...eventstore.Event) {
+ for _, event := range events {
+ switch e := event.(type) {
+ case *instance.GitLabSelfHostedIDPAddedEvent:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(&e.GitLabSelfHostedIDPAddedEvent)
+ case *instance.GitLabSelfHostedIDPChangedEvent:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(&e.GitLabSelfHostedIDPChangedEvent)
+ case *instance.IDPRemovedEvent:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(&e.RemovedEvent)
+ default:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(e)
+ }
+ }
+}
+
+func (wm *InstanceGitLabSelfHostedIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
+ return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
+ ResourceOwner(wm.ResourceOwner).
+ AddQuery().
+ AggregateTypes(instance.AggregateType).
+ AggregateIDs(wm.AggregateID).
+ EventTypes(
+ instance.GitLabSelfHostedIDPAddedEventType,
+ instance.GitLabSelfHostedIDPChangedEventType,
+ instance.IDPRemovedEventType,
+ ).
+ EventData(map[string]interface{}{"id": wm.ID}).
+ Builder()
+}
+
+func (wm *InstanceGitLabSelfHostedIDPWriteModel) NewChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ issuer,
+ clientID string,
+ clientSecretString string,
+ secretCrypto crypto.Crypto,
+ scopes []string,
+ options idp.Options,
+) (*instance.GitLabSelfHostedIDPChangedEvent, error) {
+
+ changes, err := wm.GitLabSelfHostedIDPWriteModel.NewChanges(name, issuer, clientID, clientSecretString, secretCrypto, scopes, options)
+ if err != nil || len(changes) == 0 {
+ return nil, err
+ }
+ return instance.NewGitLabSelfHostedIDPChangedEvent(ctx, aggregate, id, changes)
+}
+
type InstanceGoogleIDPWriteModel struct {
GoogleIDPWriteModel
}
@@ -458,10 +569,6 @@ func NewGoogleInstanceIDPWriteModel(instanceID, id string) *InstanceGoogleIDPWri
}
}
-func (wm *InstanceGoogleIDPWriteModel) Reduce() error {
- return wm.GoogleIDPWriteModel.Reduce()
-}
-
func (wm *InstanceGoogleIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -525,10 +632,6 @@ func NewLDAPInstanceIDPWriteModel(instanceID, id string) *InstanceLDAPIDPWriteMo
}
}
-func (wm *InstanceLDAPIDPWriteModel) Reduce() error {
- return wm.LDAPIDPWriteModel.Reduce()
-}
-
func (wm *InstanceLDAPIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -614,10 +717,6 @@ func NewInstanceIDPRemoveWriteModel(instanceID, id string) *InstanceIDPRemoveWri
}
}
-func (wm *InstanceIDPRemoveWriteModel) Reduce() error {
- return wm.IDPRemoveWriteModel.Reduce()
-}
-
func (wm *InstanceIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -631,6 +730,10 @@ func (wm *InstanceIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event)
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubIDPAddedEvent)
case *instance.GitHubEnterpriseIDPAddedEvent:
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubEnterpriseIDPAddedEvent)
+ case *instance.GitLabIDPAddedEvent:
+ wm.IDPRemoveWriteModel.AppendEvents(&e.GitLabIDPAddedEvent)
+ case *instance.GitLabSelfHostedIDPAddedEvent:
+ wm.IDPRemoveWriteModel.AppendEvents(&e.GitLabSelfHostedIDPAddedEvent)
case *instance.GoogleIDPAddedEvent:
wm.IDPRemoveWriteModel.AppendEvents(&e.GoogleIDPAddedEvent)
case *instance.LDAPIDPAddedEvent:
@@ -659,6 +762,8 @@ func (wm *InstanceIDPRemoveWriteModel) Query() *eventstore.SearchQueryBuilder {
instance.JWTIDPAddedEventType,
instance.GitHubIDPAddedEventType,
instance.GitHubEnterpriseIDPAddedEventType,
+ instance.GitLabIDPAddedEventType,
+ instance.GitLabSelfHostedIDPAddedEventType,
instance.GoogleIDPAddedEventType,
instance.LDAPIDPAddedEventType,
instance.IDPRemovedEventType,
diff --git a/internal/command/instance_idp_test.go b/internal/command/instance_idp_test.go
index 6ade24c2ad..e609a80b33 100644
--- a/internal/command/instance_idp_test.go
+++ b/internal/command/instance_idp_test.go
@@ -2,6 +2,7 @@ package command
import (
"context"
+ "errors"
"testing"
"github.com/golang/mock/gomock"
@@ -52,7 +53,9 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
provider: GenericOAuthProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-D32ef", ""))
+ },
},
},
{
@@ -68,7 +71,9 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Dbgzf", ""))
+ },
},
},
{
@@ -85,7 +90,9 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-DF4ga", ""))
+ },
},
},
{
@@ -103,7 +110,9 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-B23bs", ""))
+ },
},
},
{
@@ -122,7 +131,9 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-D2gj8", ""))
+ },
},
},
{
@@ -142,7 +153,9 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Fb8jk", ""))
+ },
},
},
{
@@ -163,7 +176,9 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sdf3f", ""))
+ },
},
},
{
@@ -329,7 +344,9 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
provider: GenericOAuthProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SAffg", ""))
+ },
},
},
{
@@ -343,7 +360,9 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
provider: GenericOAuthProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Sf3gh", ""))
+ },
},
},
{
@@ -359,7 +378,9 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SHJ3ui", ""))
+ },
},
},
{
@@ -371,11 +392,14 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
ctx: authz.WithInstanceID(context.Background(), "instance1"),
id: "id1",
provider: GenericOAuthProvider{
- Name: "name",
+ Name: "name",
+ ClientID: "clientID",
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SVrgh", ""))
+ },
},
},
{
@@ -393,7 +417,9 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-DJKeio", ""))
+ },
},
},
{
@@ -412,7 +438,9 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-ILSJi", ""))
+ },
},
},
{
@@ -432,7 +460,9 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-JKD3h", ""))
+ },
},
},
{
@@ -639,7 +669,9 @@ func TestCommandSide_AddInstanceGitHubIDP(t *testing.T) {
provider: GitHubProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Jdsgf", ""))
+ },
},
},
{
@@ -655,7 +687,9 @@ func TestCommandSide_AddInstanceGitHubIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-dsgz3", ""))
+ },
},
},
{
@@ -804,7 +838,9 @@ func TestCommandSide_UpdateInstanceGitHubIDP(t *testing.T) {
provider: GitHubProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sdf4h", ""))
+ },
},
},
{
@@ -818,7 +854,9 @@ func TestCommandSide_UpdateInstanceGitHubIDP(t *testing.T) {
provider: GitHubProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-fdh5z", ""))
+ },
},
},
{
@@ -999,7 +1037,9 @@ func TestCommandSide_AddInstanceGitHubEnterpriseIDP(t *testing.T) {
provider: GitHubEnterpriseProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Dg4td", ""))
+ },
},
},
{
@@ -1015,7 +1055,9 @@ func TestCommandSide_AddInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-dgj53", ""))
+ },
},
},
{
@@ -1032,7 +1074,9 @@ func TestCommandSide_AddInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Ghjjs", ""))
+ },
},
},
{
@@ -1050,7 +1094,9 @@ func TestCommandSide_AddInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sani2", ""))
+ },
},
},
{
@@ -1069,7 +1115,9 @@ func TestCommandSide_AddInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-agj42", ""))
+ },
},
},
{
@@ -1089,7 +1137,9 @@ func TestCommandSide_AddInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sd5hn", ""))
+ },
},
},
{
@@ -1251,7 +1301,9 @@ func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
provider: GitHubEnterpriseProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sdfh3", ""))
+ },
},
},
{
@@ -1265,7 +1317,9 @@ func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
provider: GitHubEnterpriseProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-shj42", ""))
+ },
},
},
{
@@ -1281,7 +1335,9 @@ func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sdh73", ""))
+ },
},
},
{
@@ -1293,11 +1349,14 @@ func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
ctx: authz.WithInstanceID(context.Background(), "instance1"),
id: "id1",
provider: GitHubEnterpriseProvider{
- Name: "name",
+ Name: "name",
+ ClientID: "clientID",
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-acx2w", ""))
+ },
},
},
{
@@ -1315,7 +1374,9 @@ func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-dgj6q", ""))
+ },
},
},
{
@@ -1334,7 +1395,9 @@ func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-ybj62", ""))
+ },
},
},
{
@@ -1503,6 +1566,828 @@ func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
}
}
+func TestCommandSide_AddInstanceGitLabIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ idGenerator id.Generator
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ provider GitLabProvider
+ }
+ type res struct {
+ id string
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-adsg2", ""))
+ },
+ },
+ },
+ {
+ "invalid clientSecret",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-GD1j2", ""))
+ },
+ },
+ },
+ {
+ name: "ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusherWithInstanceID(
+ "instance1",
+ instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ {
+ name: "ok all set",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusherWithInstanceID(
+ "instance1",
+ instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ []string{"openid"},
+ idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ Scopes: []string{"openid"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idGenerator: tt.fields.idGenerator,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ id, got, err := c.AddInstanceGitLabProvider(tt.args.ctx, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.id, id)
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
+func TestCommandSide_UpdateInstanceGitLabIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ id string
+ provider GitLabProvider
+ }
+ type res struct {
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid id",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-HJK91", ""))
+ },
+ },
+ },
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-D12t6", ""))
+ },
+ },
+ },
+ {
+ name: "not found",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ ),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ err: caos_errors.IsNotFound,
+ },
+ },
+ {
+ name: "no changes",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ ),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ {
+ name: "change ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusherWithInstanceID(
+ "instance1",
+ func() eventstore.Command {
+ t := true
+ event, _ := instance.NewGitLabIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ []idp.GitLabIDPChanges{
+ idp.ChangeGitLabClientID("clientID2"),
+ idp.ChangeGitLabClientSecret(&crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("newSecret"),
+ }),
+ idp.ChangeGitLabScopes([]string{"openid", "profile"}),
+ idp.ChangeGitLabOptions(idp.OptionChanges{
+ IsCreationAllowed: &t,
+ IsLinkingAllowed: &t,
+ IsAutoCreation: &t,
+ IsAutoUpdate: &t,
+ }),
+ },
+ )
+ return event
+ }(),
+ ),
+ },
+ ),
+ ),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabProvider{
+ ClientID: "clientID2",
+ ClientSecret: "newSecret",
+ Scopes: []string{"openid", "profile"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ got, err := c.UpdateInstanceGitLabProvider(tt.args.ctx, tt.args.id, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
+func TestCommandSide_AddInstanceGitLabSelfHostedIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ idGenerator id.Generator
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ provider GitLabSelfHostedProvider
+ }
+ type res struct {
+ id string
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid name",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabSelfHostedProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-jw4ZT", ""))
+ },
+ },
+ },
+ {
+ "invalid issuer",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-AST4S", ""))
+ },
+ },
+ },
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-DBZHJ", ""))
+ },
+ },
+ },
+ {
+ "invalid clientSecret",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SDGJ4", ""))
+ },
+ },
+ },
+ {
+ name: "ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusherWithInstanceID(
+ "instance1",
+ instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ {
+ name: "ok all set",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusherWithInstanceID(
+ "instance1",
+ instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ []string{"openid"},
+ idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ Scopes: []string{"openid"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idGenerator: tt.fields.idGenerator,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ id, got, err := c.AddInstanceGitLabSelfHostedProvider(tt.args.ctx, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.id, id)
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
+func TestCommandSide_UpdateInstanceGitLabSelfHostedIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ id string
+ provider GitLabSelfHostedProvider
+ }
+ type res struct {
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid id",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ provider: GitLabSelfHostedProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SAFG4", ""))
+ },
+ },
+ },
+ {
+ "invalid name",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabSelfHostedProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-DG4H", ""))
+ },
+ },
+ },
+ {
+ "invalid issuer",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SD4eb", ""))
+ },
+ },
+ },
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-GHWE3", ""))
+ },
+ },
+ },
+ {
+ name: "not found",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ ),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ err: caos_errors.IsNotFound,
+ },
+ },
+ {
+ name: "no changes",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ ),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ {
+ name: "change ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusherWithInstanceID(
+ "instance1",
+ func() eventstore.Command {
+ t := true
+ event, _ := instance.NewGitLabSelfHostedIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
+ "id1",
+ []idp.GitLabSelfHostedIDPChanges{
+ idp.ChangeGitLabSelfHostedClientID("clientID2"),
+ idp.ChangeGitLabSelfHostedIssuer("newIssuer"),
+ idp.ChangeGitLabSelfHostedName("newName"),
+ idp.ChangeGitLabSelfHostedClientSecret(&crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("newSecret"),
+ }),
+ idp.ChangeGitLabSelfHostedScopes([]string{"openid", "profile"}),
+ idp.ChangeGitLabSelfHostedOptions(idp.OptionChanges{
+ IsCreationAllowed: &t,
+ IsLinkingAllowed: &t,
+ IsAutoCreation: &t,
+ IsAutoUpdate: &t,
+ }),
+ },
+ )
+ return event
+ }(),
+ ),
+ },
+ ),
+ ),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: authz.WithInstanceID(context.Background(), "instance1"),
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Issuer: "newIssuer",
+ Name: "newName",
+ ClientID: "clientID2",
+ ClientSecret: "newSecret",
+ Scopes: []string{"openid", "profile"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "instance1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ got, err := c.UpdateInstanceGitLabSelfHostedProvider(tt.args.ctx, tt.args.id, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
func TestCommandSide_AddInstanceGoogleIDP(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
@@ -1535,7 +2420,9 @@ func TestCommandSide_AddInstanceGoogleIDP(t *testing.T) {
provider: GoogleProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-D3fvs", ""))
+ },
},
},
{
@@ -1551,7 +2438,9 @@ func TestCommandSide_AddInstanceGoogleIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-W2vqs", ""))
+ },
},
},
{
@@ -1699,7 +2588,9 @@ func TestCommandSide_UpdateInstanceGoogleIDP(t *testing.T) {
provider: GoogleProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-S32t1", ""))
+ },
},
},
{
@@ -1713,7 +2604,9 @@ func TestCommandSide_UpdateInstanceGoogleIDP(t *testing.T) {
provider: GoogleProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-ds432", ""))
+ },
},
},
{
@@ -1892,7 +2785,9 @@ func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
provider: LDAPProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SAfdd", ""))
+ },
},
},
{
@@ -1908,7 +2803,9 @@ func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SDVg2", ""))
+ },
},
},
{
@@ -1925,7 +2822,9 @@ func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sv31s", ""))
+ },
},
},
{
@@ -1943,7 +2842,9 @@ func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sdgf4", ""))
+ },
},
},
{
@@ -1962,7 +2863,9 @@ func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-AEG2w", ""))
+ },
},
},
{
@@ -1982,7 +2885,9 @@ func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SAD5n", ""))
+ },
},
},
{
@@ -2003,7 +2908,9 @@ func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sdf5h", ""))
+ },
},
},
{
@@ -2205,7 +3112,9 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
provider: LDAPProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Dgdbs", ""))
+ },
},
},
{
@@ -2219,7 +3128,9 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
provider: LDAPProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Sffgd", ""))
+ },
},
},
{
@@ -2235,7 +3146,9 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Dz62d", ""))
+ },
},
},
{
@@ -2252,7 +3165,9 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-vb3ss", ""))
+ },
},
},
{
@@ -2270,7 +3185,9 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-hbere", ""))
+ },
},
},
{
@@ -2289,7 +3206,9 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-ASFt6", ""))
+ },
},
},
{
@@ -2309,7 +3228,9 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-DG45z", ""))
+ },
},
},
{
diff --git a/internal/command/org_idp.go b/internal/command/org_idp.go
index b244d7d33a..ca7ad66d27 100644
--- a/internal/command/org_idp.go
+++ b/internal/command/org_idp.go
@@ -212,6 +212,86 @@ func (c *Commands) UpdateOrgGitHubEnterpriseProvider(ctx context.Context, resour
return pushedEventsToObjectDetails(pushedEvents), nil
}
+func (c *Commands) AddOrgGitLabProvider(ctx context.Context, resourceOwner string, provider GitLabProvider) (string, *domain.ObjectDetails, error) {
+ orgAgg := org.NewAggregate(resourceOwner)
+ id, err := c.idGenerator.Next()
+ if err != nil {
+ return "", nil, err
+ }
+ writeModel := NewGitLabOrgIDPWriteModel(resourceOwner, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgGitLabProvider(orgAgg, writeModel, provider))
+ if err != nil {
+ return "", nil, err
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return "", nil, err
+ }
+ return id, pushedEventsToObjectDetails(pushedEvents), nil
+}
+
+func (c *Commands) UpdateOrgGitLabProvider(ctx context.Context, resourceOwner, id string, provider GitLabProvider) (*domain.ObjectDetails, error) {
+ orgAgg := org.NewAggregate(resourceOwner)
+ writeModel := NewGitLabOrgIDPWriteModel(resourceOwner, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgGitLabProvider(orgAgg, writeModel, provider))
+ if err != nil {
+ return nil, err
+ }
+ if len(cmds) == 0 {
+ // no change, so return directly
+ return &domain.ObjectDetails{
+ Sequence: writeModel.ProcessedSequence,
+ EventDate: writeModel.ChangeDate,
+ ResourceOwner: writeModel.ResourceOwner,
+ }, nil
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return nil, err
+ }
+ return pushedEventsToObjectDetails(pushedEvents), nil
+}
+
+func (c *Commands) AddOrgGitLabSelfHostedProvider(ctx context.Context, resourceOwner string, provider GitLabSelfHostedProvider) (string, *domain.ObjectDetails, error) {
+ orgAgg := org.NewAggregate(resourceOwner)
+ id, err := c.idGenerator.Next()
+ if err != nil {
+ return "", nil, err
+ }
+ writeModel := NewGitLabSelfHostedOrgIDPWriteModel(resourceOwner, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgGitLabSelfHostedProvider(orgAgg, writeModel, provider))
+ if err != nil {
+ return "", nil, err
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return "", nil, err
+ }
+ return id, pushedEventsToObjectDetails(pushedEvents), nil
+}
+
+func (c *Commands) UpdateOrgGitLabSelfHostedProvider(ctx context.Context, resourceOwner, id string, provider GitLabSelfHostedProvider) (*domain.ObjectDetails, error) {
+ orgAgg := org.NewAggregate(resourceOwner)
+ writeModel := NewGitLabSelfHostedOrgIDPWriteModel(resourceOwner, id)
+ cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgGitLabSelfHostedProvider(orgAgg, writeModel, provider))
+ if err != nil {
+ return nil, err
+ }
+ if len(cmds) == 0 {
+ // no change, so return directly
+ return &domain.ObjectDetails{
+ Sequence: writeModel.ProcessedSequence,
+ EventDate: writeModel.ChangeDate,
+ ResourceOwner: writeModel.ResourceOwner,
+ }, nil
+ }
+ pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if err != nil {
+ return nil, err
+ }
+ return pushedEventsToObjectDetails(pushedEvents), nil
+}
+
func (c *Commands) AddOrgGoogleProvider(ctx context.Context, resourceOwner string, provider GoogleProvider) (string, *domain.ObjectDetails, error) {
orgAgg := org.NewAggregate(resourceOwner)
id, err := c.idGenerator.Next()
@@ -808,6 +888,178 @@ func (c *Commands) prepareUpdateOrgGitHubEnterpriseProvider(a *org.Aggregate, wr
}
}
+func (c *Commands) prepareAddOrgGitLabProvider(a *org.Aggregate, writeModel *OrgGitLabIDPWriteModel, provider GitLabProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-adsg2", "Errors.Invalid.Argument")
+ }
+ if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-GD1j2", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
+ if err != nil {
+ return nil, err
+ }
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ secret, err := crypto.Encrypt([]byte(provider.ClientSecret), c.idpConfigEncryption)
+ if err != nil {
+ return nil, err
+ }
+ return []eventstore.Command{
+ org.NewGitLabIDPAddedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.ClientID,
+ secret,
+ provider.Scopes,
+ provider.IDPOptions,
+ ),
+ }, nil
+ }, nil
+ }
+}
+
+func (c *Commands) prepareUpdateOrgGitLabProvider(a *org.Aggregate, writeModel *OrgGitLabIDPWriteModel, provider GitLabProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-HJK91", "Errors.Invalid.Argument")
+ }
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-D12t6", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
+ if err != nil {
+ return nil, err
+ }
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ if !writeModel.State.Exists() {
+ return nil, caos_errs.ThrowNotFound(nil, "ORG-HBReq", "Errors.Org.IDPConfig.NotExisting")
+ }
+ event, err := writeModel.NewChangedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.ClientID,
+ provider.ClientSecret,
+ c.idpConfigEncryption,
+ provider.Scopes,
+ provider.IDPOptions,
+ )
+ if err != nil {
+ return nil, err
+ }
+ if event == nil {
+ return nil, nil
+ }
+ return []eventstore.Command{event}, nil
+ }, nil
+ }
+}
+
+func (c *Commands) prepareAddOrgGitLabSelfHostedProvider(a *org.Aggregate, writeModel *OrgGitLabSelfHostedIDPWriteModel, provider GitLabSelfHostedProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-jw4ZT", "Errors.Invalid.Argument")
+ }
+ if provider.Issuer = strings.TrimSpace(provider.Issuer); provider.Issuer == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-AST4S", "Errors.Invalid.Argument")
+ }
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-DBZHJ", "Errors.Invalid.Argument")
+ }
+ if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-SDGJ4", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
+ if err != nil {
+ return nil, err
+ }
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ secret, err := crypto.Encrypt([]byte(provider.ClientSecret), c.idpConfigEncryption)
+ if err != nil {
+ return nil, err
+ }
+ return []eventstore.Command{
+ org.NewGitLabSelfHostedIDPAddedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.Issuer,
+ provider.ClientID,
+ secret,
+ provider.Scopes,
+ provider.IDPOptions,
+ ),
+ }, nil
+ }, nil
+ }
+}
+
+func (c *Commands) prepareUpdateOrgGitLabSelfHostedProvider(a *org.Aggregate, writeModel *OrgGitLabSelfHostedIDPWriteModel, provider GitLabSelfHostedProvider) preparation.Validation {
+ return func() (preparation.CreateCommands, error) {
+ if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-SAFG4", "Errors.Invalid.Argument")
+ }
+ if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-DG4H", "Errors.Invalid.Argument")
+ }
+ if provider.Issuer = strings.TrimSpace(provider.Issuer); provider.Issuer == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-SD4eb", "Errors.Invalid.Argument")
+ }
+ if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
+ return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-GHWE3", "Errors.Invalid.Argument")
+ }
+ return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
+ events, err := filter(ctx, writeModel.Query())
+ if err != nil {
+ return nil, err
+ }
+ writeModel.AppendEvents(events...)
+ if err = writeModel.Reduce(); err != nil {
+ return nil, err
+ }
+ if !writeModel.State.Exists() {
+ return nil, caos_errs.ThrowNotFound(nil, "ORG-D2tg1", "Errors.Org.IDPConfig.NotExisting")
+ }
+ event, err := writeModel.NewChangedEvent(
+ ctx,
+ &a.Aggregate,
+ writeModel.ID,
+ provider.Name,
+ provider.Issuer,
+ provider.ClientID,
+ provider.ClientSecret,
+ c.idpConfigEncryption,
+ provider.Scopes,
+ provider.IDPOptions,
+ )
+ if err != nil {
+ return nil, err
+ }
+ if event == nil {
+ return nil, nil
+ }
+ return []eventstore.Command{event}, nil
+ }, nil
+ }
+}
+
func (c *Commands) prepareAddOrgGoogleProvider(a *org.Aggregate, writeModel *OrgGoogleIDPWriteModel, provider GoogleProvider) preparation.Validation {
return func() (preparation.CreateCommands, error) {
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
diff --git a/internal/command/org_idp_model.go b/internal/command/org_idp_model.go
index c972656e0d..c8335885b2 100644
--- a/internal/command/org_idp_model.go
+++ b/internal/command/org_idp_model.go
@@ -25,10 +25,6 @@ func NewOAuthOrgIDPWriteModel(orgID, id string) *OrgOAuthIDPWriteModel {
}
}
-func (wm *OrgOAuthIDPWriteModel) Reduce() error {
- return wm.OAuthIDPWriteModel.Reduce()
-}
-
func (wm *OrgOAuthIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -109,10 +105,6 @@ func NewOIDCOrgIDPWriteModel(orgID, id string) *OrgOIDCIDPWriteModel {
}
}
-func (wm *OrgOIDCIDPWriteModel) Reduce() error {
- return wm.OIDCIDPWriteModel.Reduce()
-}
-
func (wm *OrgOIDCIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -210,10 +202,6 @@ func NewJWTOrgIDPWriteModel(orgID, id string) *OrgJWTIDPWriteModel {
}
}
-func (wm *OrgJWTIDPWriteModel) Reduce() error {
- return wm.JWTIDPWriteModel.Reduce()
-}
-
func (wm *OrgJWTIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -309,10 +297,6 @@ func NewGitHubOrgIDPWriteModel(orgID, id string) *OrgGitHubIDPWriteModel {
}
}
-func (wm *OrgGitHubIDPWriteModel) Reduce() error {
- return wm.GitHubIDPWriteModel.Reduce()
-}
-
func (wm *OrgGitHubIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -379,10 +363,6 @@ func NewGitHubEnterpriseOrgIDPWriteModel(orgID, id string) *OrgGitHubEnterpriseI
}
}
-func (wm *OrgGitHubEnterpriseIDPWriteModel) Reduce() error {
- return wm.GitHubEnterpriseIDPWriteModel.Reduce()
-}
-
func (wm *OrgGitHubEnterpriseIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -446,6 +426,137 @@ func (wm *OrgGitHubEnterpriseIDPWriteModel) NewChangedEvent(
return org.NewGitHubEnterpriseIDPChangedEvent(ctx, aggregate, id, changes)
}
+type OrgGitLabIDPWriteModel struct {
+ GitLabIDPWriteModel
+}
+
+func NewGitLabOrgIDPWriteModel(orgID, id string) *OrgGitLabIDPWriteModel {
+ return &OrgGitLabIDPWriteModel{
+ GitLabIDPWriteModel{
+ WriteModel: eventstore.WriteModel{
+ AggregateID: orgID,
+ ResourceOwner: orgID,
+ },
+ ID: id,
+ },
+ }
+}
+
+func (wm *OrgGitLabIDPWriteModel) AppendEvents(events ...eventstore.Event) {
+ for _, event := range events {
+ switch e := event.(type) {
+ case *org.GitLabIDPAddedEvent:
+ wm.GitLabIDPWriteModel.AppendEvents(&e.GitLabIDPAddedEvent)
+ case *org.GitLabIDPChangedEvent:
+ wm.GitLabIDPWriteModel.AppendEvents(&e.GitLabIDPChangedEvent)
+ case *org.IDPRemovedEvent:
+ wm.GitLabIDPWriteModel.AppendEvents(&e.RemovedEvent)
+ default:
+ wm.GitLabIDPWriteModel.AppendEvents(e)
+ }
+ }
+}
+
+func (wm *OrgGitLabIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
+ return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
+ ResourceOwner(wm.ResourceOwner).
+ AddQuery().
+ AggregateTypes(org.AggregateType).
+ AggregateIDs(wm.AggregateID).
+ EventTypes(
+ org.GitLabIDPAddedEventType,
+ org.GitLabIDPChangedEventType,
+ org.IDPRemovedEventType,
+ ).
+ EventData(map[string]interface{}{"id": wm.ID}).
+ Builder()
+}
+
+func (wm *OrgGitLabIDPWriteModel) NewChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ clientID,
+ clientSecretString string,
+ secretCrypto crypto.Crypto,
+ scopes []string,
+ options idp.Options,
+) (*org.GitLabIDPChangedEvent, error) {
+
+ changes, err := wm.GitLabIDPWriteModel.NewChanges(name, clientID, clientSecretString, secretCrypto, scopes, options)
+ if err != nil || len(changes) == 0 {
+ return nil, err
+ }
+ return org.NewGitLabIDPChangedEvent(ctx, aggregate, id, changes)
+}
+
+type OrgGitLabSelfHostedIDPWriteModel struct {
+ GitLabSelfHostedIDPWriteModel
+}
+
+func NewGitLabSelfHostedOrgIDPWriteModel(orgID, id string) *OrgGitLabSelfHostedIDPWriteModel {
+ return &OrgGitLabSelfHostedIDPWriteModel{
+ GitLabSelfHostedIDPWriteModel{
+ WriteModel: eventstore.WriteModel{
+ AggregateID: orgID,
+ ResourceOwner: orgID,
+ },
+ ID: id,
+ },
+ }
+}
+
+func (wm *OrgGitLabSelfHostedIDPWriteModel) AppendEvents(events ...eventstore.Event) {
+ for _, event := range events {
+ switch e := event.(type) {
+ case *org.GitLabSelfHostedIDPAddedEvent:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(&e.GitLabSelfHostedIDPAddedEvent)
+ case *org.GitLabSelfHostedIDPChangedEvent:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(&e.GitLabSelfHostedIDPChangedEvent)
+ case *org.IDPRemovedEvent:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(&e.RemovedEvent)
+ default:
+ wm.GitLabSelfHostedIDPWriteModel.AppendEvents(e)
+ }
+ }
+}
+
+func (wm *OrgGitLabSelfHostedIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
+ return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
+ ResourceOwner(wm.ResourceOwner).
+ AddQuery().
+ AggregateTypes(org.AggregateType).
+ AggregateIDs(wm.AggregateID).
+ EventTypes(
+ org.GitLabSelfHostedIDPAddedEventType,
+ org.GitLabSelfHostedIDPChangedEventType,
+ org.IDPRemovedEventType,
+ ).
+ EventData(map[string]interface{}{"id": wm.ID}).
+ Builder()
+}
+
+func (wm *OrgGitLabSelfHostedIDPWriteModel) NewChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ issuer,
+ clientID string,
+ clientSecretString string,
+ secretCrypto crypto.Crypto,
+ scopes []string,
+ options idp.Options,
+) (*org.GitLabSelfHostedIDPChangedEvent, error) {
+
+ changes, err := wm.GitLabSelfHostedIDPWriteModel.NewChanges(name, issuer, clientID, clientSecretString, secretCrypto, scopes, options)
+ if err != nil || len(changes) == 0 {
+ return nil, err
+ }
+ return org.NewGitLabSelfHostedIDPChangedEvent(ctx, aggregate, id, changes)
+}
+
type OrgGoogleIDPWriteModel struct {
GoogleIDPWriteModel
}
@@ -462,10 +573,6 @@ func NewGoogleOrgIDPWriteModel(orgID, id string) *OrgGoogleIDPWriteModel {
}
}
-func (wm *OrgGoogleIDPWriteModel) Reduce() error {
- return wm.GoogleIDPWriteModel.Reduce()
-}
-
func (wm *OrgGoogleIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -531,10 +638,6 @@ func NewLDAPOrgIDPWriteModel(orgID, id string) *OrgLDAPIDPWriteModel {
}
}
-func (wm *OrgLDAPIDPWriteModel) Reduce() error {
- return wm.LDAPIDPWriteModel.Reduce()
-}
-
func (wm *OrgLDAPIDPWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -620,10 +723,6 @@ func NewOrgIDPRemoveWriteModel(orgID, id string) *OrgIDPRemoveWriteModel {
}
}
-func (wm *OrgIDPRemoveWriteModel) Reduce() error {
- return wm.IDPRemoveWriteModel.Reduce()
-}
-
func (wm *OrgIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
@@ -637,6 +736,10 @@ func (wm *OrgIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event) {
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubIDPAddedEvent)
case *org.GitHubEnterpriseIDPAddedEvent:
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubEnterpriseIDPAddedEvent)
+ case *org.GitLabIDPAddedEvent:
+ wm.IDPRemoveWriteModel.AppendEvents(&e.GitLabIDPAddedEvent)
+ case *org.GitLabSelfHostedIDPAddedEvent:
+ wm.IDPRemoveWriteModel.AppendEvents(&e.GitLabSelfHostedIDPAddedEvent)
case *org.GoogleIDPAddedEvent:
wm.IDPRemoveWriteModel.AppendEvents(&e.GoogleIDPAddedEvent)
case *org.LDAPIDPAddedEvent:
@@ -665,6 +768,8 @@ func (wm *OrgIDPRemoveWriteModel) Query() *eventstore.SearchQueryBuilder {
org.JWTIDPAddedEventType,
org.GitHubIDPAddedEventType,
org.GitHubEnterpriseIDPAddedEventType,
+ org.GitLabIDPAddedEventType,
+ org.GitLabSelfHostedIDPAddedEventType,
org.GoogleIDPAddedEventType,
org.LDAPIDPAddedEventType,
org.IDPRemovedEventType,
diff --git a/internal/command/org_idp_test.go b/internal/command/org_idp_test.go
index 9337fc61e6..b15f8e515c 100644
--- a/internal/command/org_idp_test.go
+++ b/internal/command/org_idp_test.go
@@ -2,6 +2,7 @@ package command
import (
"context"
+ "errors"
"testing"
"github.com/golang/mock/gomock"
@@ -11,6 +12,7 @@ import (
"github.com/zitadel/zitadel/internal/domain"
caos_errors "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
+ "github.com/zitadel/zitadel/internal/eventstore/repository"
"github.com/zitadel/zitadel/internal/id"
id_mock "github.com/zitadel/zitadel/internal/id/mock"
"github.com/zitadel/zitadel/internal/repository/idp"
@@ -52,7 +54,9 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
provider: GenericOAuthProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-D32ef", ""))
+ },
},
},
{
@@ -69,7 +73,9 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Dbgzf", ""))
+ },
},
},
{
@@ -87,7 +93,9 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-DF4ga", ""))
+ },
},
},
{
@@ -106,7 +114,9 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-B23bs", ""))
+ },
},
},
{
@@ -126,7 +136,9 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-D2gj8", ""))
+ },
},
},
{
@@ -147,7 +159,9 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Fb8jk", ""))
+ },
},
},
{
@@ -169,7 +183,9 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sadf3d", ""))
+ },
},
},
{
@@ -333,7 +349,9 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
provider: GenericOAuthProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-asfsa", ""))
+ },
},
},
{
@@ -348,7 +366,9 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
provider: GenericOAuthProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-D32ef", ""))
+ },
},
},
{
@@ -365,7 +385,9 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Dbgzf", ""))
+ },
},
},
{
@@ -378,11 +400,14 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
resourceOwner: "org1",
id: "id1",
provider: GenericOAuthProvider{
- Name: "name",
+ Name: "name",
+ ClientID: "clientID",
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-B23bs", ""))
+ },
},
},
{
@@ -401,7 +426,9 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-D2gj8", ""))
+ },
},
},
{
@@ -421,7 +448,9 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Fb8jk", ""))
+ },
},
},
{
@@ -442,7 +471,9 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SAe4gh", ""))
+ },
},
},
{
@@ -651,7 +682,9 @@ func TestCommandSide_AddOrgGitHubIDP(t *testing.T) {
provider: GitHubProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Jdsgf", ""))
+ },
},
},
{
@@ -668,7 +701,9 @@ func TestCommandSide_AddOrgGitHubIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-dsgz3", ""))
+ },
},
},
{
@@ -815,7 +850,9 @@ func TestCommandSide_UpdateOrgGitHubIDP(t *testing.T) {
provider: GitHubProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sdf4h", ""))
+ },
},
},
{
@@ -830,7 +867,9 @@ func TestCommandSide_UpdateOrgGitHubIDP(t *testing.T) {
provider: GitHubProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-fdh5z", ""))
+ },
},
},
{
@@ -1013,7 +1052,9 @@ func TestCommandSide_AddOrgGitHubEnterpriseIDP(t *testing.T) {
provider: GitHubEnterpriseProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Dg4td", ""))
+ },
},
},
{
@@ -1030,7 +1071,9 @@ func TestCommandSide_AddOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-dgj53", ""))
+ },
},
},
{
@@ -1048,7 +1091,9 @@ func TestCommandSide_AddOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Ghjjs", ""))
+ },
},
},
{
@@ -1067,7 +1112,9 @@ func TestCommandSide_AddOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sani2", ""))
+ },
},
},
{
@@ -1087,7 +1134,9 @@ func TestCommandSide_AddOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-agj42", ""))
+ },
},
},
{
@@ -1108,7 +1157,9 @@ func TestCommandSide_AddOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sd5hn", ""))
+ },
},
},
{
@@ -1268,7 +1319,9 @@ func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
provider: GitHubEnterpriseProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sdfh3", ""))
+ },
},
},
{
@@ -1283,7 +1336,9 @@ func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
provider: GitHubEnterpriseProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-shj42", ""))
+ },
},
},
{
@@ -1300,7 +1355,9 @@ func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sdh73", ""))
+ },
},
},
{
@@ -1313,11 +1370,14 @@ func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
resourceOwner: "org1",
id: "id1",
provider: GitHubEnterpriseProvider{
- Name: "name",
+ Name: "name",
+ ClientID: "clientID",
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-acx2w", ""))
+ },
},
},
{
@@ -1336,7 +1396,9 @@ func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-dgj6q", ""))
+ },
},
},
{
@@ -1356,7 +1418,9 @@ func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-ybj62", ""))
+ },
},
},
{
@@ -1525,6 +1589,848 @@ func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
}
}
+func TestCommandSide_AddOrgGitLabIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ idGenerator id.Generator
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ resourceOwner string
+ provider GitLabProvider
+ }
+ type res struct {
+ id string
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-adsg2", ""))
+ },
+ },
+ },
+ {
+ "invalid clientSecret",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-GD1j2", ""))
+ },
+ },
+ },
+ {
+ name: "ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusher(
+ org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ {
+ name: "ok all set",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusher(
+ org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ []string{"openid"},
+ idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ Scopes: []string{"openid"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idGenerator: tt.fields.idGenerator,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ id, got, err := c.AddOrgGitLabProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.id, id)
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
+func TestCommandSide_UpdateOrgGitLabIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ resourceOwner string
+ id string
+ provider GitLabProvider
+ }
+ type res struct {
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid id",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-HJK91", ""))
+ },
+ },
+ },
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-D12t6", ""))
+ },
+ },
+ },
+ {
+ name: "not found",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ ),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ err: caos_errors.IsNotFound,
+ },
+ },
+ {
+ name: "no changes",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ ),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabProvider{
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ {
+ name: "change ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusher(
+ func() eventstore.Command {
+ t := true
+ event, _ := org.NewGitLabIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ []idp.GitLabIDPChanges{
+ idp.ChangeGitLabClientID("clientID2"),
+ idp.ChangeGitLabClientSecret(&crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("newSecret"),
+ }),
+ idp.ChangeGitLabScopes([]string{"openid", "profile"}),
+ idp.ChangeGitLabOptions(idp.OptionChanges{
+ IsCreationAllowed: &t,
+ IsLinkingAllowed: &t,
+ IsAutoCreation: &t,
+ IsAutoUpdate: &t,
+ }),
+ },
+ )
+ return event
+ }(),
+ ),
+ },
+ ),
+ ),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabProvider{
+ ClientID: "clientID2",
+ ClientSecret: "newSecret",
+ Scopes: []string{"openid", "profile"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ got, err := c.UpdateOrgGitLabProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
+func TestCommandSide_AddOrgGitLabSelfHostedIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ idGenerator id.Generator
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ resourceOwner string
+ provider GitLabSelfHostedProvider
+ }
+ type res struct {
+ id string
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid name",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabSelfHostedProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-jw4ZT", ""))
+ },
+ },
+ },
+ {
+ "invalid issuer",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-AST4S", ""))
+ },
+ },
+ },
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-DBZHJ", ""))
+ },
+ },
+ },
+ {
+ "invalid clientSecret",
+ fields{
+ eventstore: eventstoreExpect(t),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SDGJ4", ""))
+ },
+ },
+ },
+ {
+ name: "ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusher(
+ org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ {
+ name: "ok all set",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusher(
+ org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ []string{"openid"},
+ idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ )),
+ },
+ ),
+ ),
+ idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ ClientSecret: "clientSecret",
+ Scopes: []string{"openid"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ id: "id1",
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idGenerator: tt.fields.idGenerator,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ id, got, err := c.AddOrgGitLabSelfHostedProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.id, id)
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
+func TestCommandSide_UpdateOrgGitLabSelfHostedIDP(t *testing.T) {
+ type fields struct {
+ eventstore *eventstore.Eventstore
+ secretCrypto crypto.EncryptionAlgorithm
+ }
+ type args struct {
+ ctx context.Context
+ resourceOwner string
+ id string
+ provider GitLabSelfHostedProvider
+ }
+ type res struct {
+ want *domain.ObjectDetails
+ err func(error) bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ res res
+ }{
+ {
+ "invalid id",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ provider: GitLabSelfHostedProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SAFG4", ""))
+ },
+ },
+ },
+ {
+ "invalid name",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabSelfHostedProvider{},
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-DG4H", ""))
+ },
+ },
+ },
+ {
+ "invalid issuer",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SD4eb", ""))
+ },
+ },
+ },
+ {
+ "invalid clientID",
+ fields{
+ eventstore: eventstoreExpect(t),
+ },
+ args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ },
+ },
+ res{
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-GHWE3", ""))
+ },
+ },
+ },
+ {
+ name: "not found",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(),
+ ),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ err: caos_errors.IsNotFound,
+ },
+ },
+ {
+ name: "no changes",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ ),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Name: "name",
+ Issuer: "issuer",
+ ClientID: "clientID",
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ {
+ name: "change ok",
+ fields: fields{
+ eventstore: eventstoreExpect(t,
+ expectFilter(
+ eventFromEventPusher(
+ org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ "name",
+ "issuer",
+ "clientID",
+ &crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("clientSecret"),
+ },
+ nil,
+ idp.Options{},
+ )),
+ ),
+ expectPush(
+ []*repository.Event{
+ eventFromEventPusher(
+ func() eventstore.Command {
+ t := true
+ event, _ := org.NewGitLabSelfHostedIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
+ "id1",
+ []idp.GitLabSelfHostedIDPChanges{
+ idp.ChangeGitLabSelfHostedClientID("clientID2"),
+ idp.ChangeGitLabSelfHostedIssuer("newIssuer"),
+ idp.ChangeGitLabSelfHostedName("newName"),
+ idp.ChangeGitLabSelfHostedClientSecret(&crypto.CryptoValue{
+ CryptoType: crypto.TypeEncryption,
+ Algorithm: "enc",
+ KeyID: "id",
+ Crypted: []byte("newSecret"),
+ }),
+ idp.ChangeGitLabSelfHostedScopes([]string{"openid", "profile"}),
+ idp.ChangeGitLabSelfHostedOptions(idp.OptionChanges{
+ IsCreationAllowed: &t,
+ IsLinkingAllowed: &t,
+ IsAutoCreation: &t,
+ IsAutoUpdate: &t,
+ }),
+ },
+ )
+ return event
+ }(),
+ ),
+ },
+ ),
+ ),
+ secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
+ },
+ args: args{
+ ctx: context.Background(),
+ resourceOwner: "org1",
+ id: "id1",
+ provider: GitLabSelfHostedProvider{
+ Issuer: "newIssuer",
+ Name: "newName",
+ ClientID: "clientID2",
+ ClientSecret: "newSecret",
+ Scopes: []string{"openid", "profile"},
+ IDPOptions: idp.Options{
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ },
+ },
+ },
+ res: res{
+ want: &domain.ObjectDetails{ResourceOwner: "org1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &Commands{
+ eventstore: tt.fields.eventstore,
+ idpConfigEncryption: tt.fields.secretCrypto,
+ }
+ got, err := c.UpdateOrgGitLabSelfHostedProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
+ if tt.res.err == nil {
+ assert.NoError(t, err)
+ }
+ if tt.res.err != nil && !tt.res.err(err) {
+ t.Errorf("got wrong err: %v ", err)
+ }
+ if tt.res.err == nil {
+ assert.Equal(t, tt.res.want, got)
+ }
+ })
+ }
+}
+
func TestCommandSide_AddOrgGoogleIDP(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
@@ -1559,7 +2465,9 @@ func TestCommandSide_AddOrgGoogleIDP(t *testing.T) {
provider: GoogleProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-D3fvs", ""))
+ },
},
},
{
@@ -1576,7 +2484,9 @@ func TestCommandSide_AddOrgGoogleIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-W2vqs", ""))
+ },
},
},
{
@@ -1722,7 +2632,9 @@ func TestCommandSide_UpdateOrgGoogleIDP(t *testing.T) {
provider: GoogleProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-S32t1", ""))
+ },
},
},
{
@@ -1737,7 +2649,9 @@ func TestCommandSide_UpdateOrgGoogleIDP(t *testing.T) {
provider: GoogleProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-ds432", ""))
+ },
},
},
{
@@ -1918,7 +2832,9 @@ func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
provider: LDAPProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SAfdd", ""))
+ },
},
},
{
@@ -1935,7 +2851,9 @@ func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SDVg2", ""))
+ },
},
},
{
@@ -1953,7 +2871,9 @@ func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sv31s", ""))
+ },
},
},
{
@@ -1972,7 +2892,9 @@ func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sdgf4", ""))
+ },
},
},
{
@@ -1992,7 +2914,9 @@ func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-AEG2w", ""))
+ },
},
},
{
@@ -2013,7 +2937,9 @@ func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SAD5n", ""))
+ },
},
},
{
@@ -2035,7 +2961,9 @@ func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sdf5h", ""))
+ },
},
},
{
@@ -2235,7 +3163,9 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
provider: LDAPProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Dgdbs", ""))
+ },
},
},
{
@@ -2250,7 +3180,9 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
provider: LDAPProvider{},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Sffgd", ""))
+ },
},
},
{
@@ -2267,7 +3199,9 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Dz62d", ""))
+ },
},
},
{
@@ -2285,7 +3219,9 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-vb3ss", ""))
+ },
},
},
{
@@ -2304,7 +3240,9 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-hbere", ""))
+ },
},
},
{
@@ -2324,7 +3262,9 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-ASFt6", ""))
+ },
},
},
{
@@ -2345,7 +3285,9 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
},
},
res{
- err: caos_errors.IsErrorInvalidArgument,
+ err: func(err error) bool {
+ return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-DG45z", ""))
+ },
},
},
{
diff --git a/internal/domain/idp.go b/internal/domain/idp.go
index 3c1d33e411..5e4959d182 100644
--- a/internal/domain/idp.go
+++ b/internal/domain/idp.go
@@ -36,12 +36,22 @@ const (
)
func (t IDPType) GetCSSClass() string {
- switch t { //nolint:exhaustive
+ switch t {
case IDPTypeGoogle:
return "google"
case IDPTypeGitHub,
IDPTypeGitHubEnterprise:
return "github"
+ case IDPTypeGitLab,
+ IDPTypeGitLabSelfHosted:
+ return "gitlab"
+ case IDPTypeUnspecified,
+ IDPTypeOIDC,
+ IDPTypeJWT,
+ IDPTypeOAuth,
+ IDPTypeLDAP,
+ IDPTypeAzureAD:
+ fallthrough
default:
return ""
}
diff --git a/internal/domain/policy_login.go b/internal/domain/policy_login.go
index a0c9d4bce7..b8019974e1 100644
--- a/internal/domain/policy_login.go
+++ b/internal/domain/policy_login.go
@@ -4,6 +4,8 @@ import (
"net/url"
"time"
+ "github.com/zitadel/logging"
+
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
)
@@ -65,6 +67,35 @@ func (p IDPProvider) IsValid() bool {
return p.IDPConfigID != ""
}
+// DisplayName returns the name or a default
+// to be used when always a name must be displayed (e.g. login)
+func (p IDPProvider) DisplayName() string {
+ if p.Name != "" {
+ return p.Name
+ }
+ switch p.IDPType {
+ case IDPTypeGitHub:
+ return "GitHub"
+ case IDPTypeGitLab:
+ return "GitLab"
+ case IDPTypeGoogle:
+ return "Google"
+ case IDPTypeUnspecified,
+ IDPTypeOIDC,
+ IDPTypeJWT,
+ IDPTypeOAuth,
+ IDPTypeLDAP,
+ IDPTypeAzureAD,
+ IDPTypeGitHubEnterprise,
+ IDPTypeGitLabSelfHosted:
+ fallthrough
+ default:
+ // we should never get here, so log it
+ logging.Errorf("name of provider (type %d) is empty - id: %s", p.IDPType, p.IDPConfigID)
+ return ""
+ }
+}
+
type PasswordlessType int32
const (
diff --git a/internal/idp/providers/gitlab/gitlab.go b/internal/idp/providers/gitlab/gitlab.go
index f36aba8f23..1bb02302f3 100644
--- a/internal/idp/providers/gitlab/gitlab.go
+++ b/internal/idp/providers/gitlab/gitlab.go
@@ -1,6 +1,8 @@
package gitlab
import (
+ openid "github.com/zitadel/oidc/v2/pkg/oidc"
+
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/idp/providers/oidc"
)
@@ -25,6 +27,14 @@ func New(clientID, clientSecret, redirectURI string, scopes []string, options ..
// NewCustomIssuer creates a GitLab provider using the [oidc.Provider] (OIDC generic provider)
// with a custom issuer for self-managed instances
func NewCustomIssuer(name, issuer, clientID, clientSecret, redirectURI string, scopes []string, options ...oidc.ProviderOpts) (*Provider, error) {
+ if len(scopes) == 0 {
+ // the OIDC provider would set `openid profile email phone` as default scope,
+ // but since gitlab does not handle unknown scopes correctly (phone) and returns an error,
+ // we will just set a separate default list
+ scopes = []string{openid.ScopeOpenID, openid.ScopeProfile, openid.ScopeEmail}
+ }
+ // gitlab is currently not able to handle the prompt `select_account`:
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/377368
rp, err := oidc.New(name, issuer, clientID, clientSecret, redirectURI, scopes, oidc.DefaultMapper, options...)
if err != nil {
return nil, err
diff --git a/internal/idp/providers/gitlab/gitlab_test.go b/internal/idp/providers/gitlab/gitlab_test.go
index c6660a3e99..74fd66ccbc 100644
--- a/internal/idp/providers/gitlab/gitlab_test.go
+++ b/internal/idp/providers/gitlab/gitlab_test.go
@@ -33,7 +33,18 @@ func TestProvider_BeginAuth(t *testing.T) {
scopes: []string{"openid"},
},
want: &oidc.Session{
- AuthURL: "https://gitlab.com/oauth/authorize?client_id=clientID&prompt=select_account&redirect_uri=redirectURI&response_type=code&scope=openid&state=testState",
+ AuthURL: "https://gitlab.com/oauth/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=openid&state=testState",
+ },
+ },
+ {
+ name: "successful auth default scopes",
+ fields: fields{
+ clientID: "clientID",
+ clientSecret: "clientSecret",
+ redirectURI: "redirectURI",
+ },
+ want: &oidc.Session{
+ AuthURL: "https://gitlab.com/oauth/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=openid+profile+email&state=testState",
},
},
}
diff --git a/internal/idp/providers/google/google.go b/internal/idp/providers/google/google.go
index 67a958692b..d850a173d2 100644
--- a/internal/idp/providers/google/google.go
+++ b/internal/idp/providers/google/google.go
@@ -21,7 +21,7 @@ type Provider struct {
// New creates a Google provider using the [oidc.Provider] (OIDC generic provider)
func New(clientID, clientSecret, redirectURI string, scopes []string, opts ...oidc.ProviderOpts) (*Provider, error) {
- rp, err := oidc.New(name, issuer, clientID, clientSecret, redirectURI, scopes, userMapper, opts...)
+ rp, err := oidc.New(name, issuer, clientID, clientSecret, redirectURI, scopes, userMapper, append(opts, oidc.WithSelectAccount())...)
if err != nil {
return nil, err
}
diff --git a/internal/idp/providers/oidc/oidc.go b/internal/idp/providers/oidc/oidc.go
index 81d77d5a32..c8f86dd7a3 100644
--- a/internal/idp/providers/oidc/oidc.go
+++ b/internal/idp/providers/oidc/oidc.go
@@ -21,6 +21,7 @@ type Provider struct {
isAutoCreation bool
isAutoUpdate bool
userInfoMapper func(info oidc.UserInfo) idp.User
+ authOptions []rp.AuthURLOpt
}
type ProviderOpts func(provider *Provider)
@@ -61,6 +62,13 @@ func WithRelyingPartyOption(option rp.Option) ProviderOpts {
}
}
+// WithSelectAccount adds the select_account prompt to the auth request
+func WithSelectAccount() ProviderOpts {
+ return func(p *Provider) {
+ p.authOptions = append(p.authOptions, rp.WithPrompt(oidc.PromptSelectAccount))
+ }
+}
+
type UserInfoMapper func(info oidc.UserInfo) idp.User
var DefaultMapper UserInfoMapper = func(info oidc.UserInfo) idp.User {
@@ -105,7 +113,7 @@ func (p *Provider) Name() string {
// BeginAuth implements the [idp.Provider] interface.
// It will create a [Session] with an OIDC authorization request as AuthURL.
func (p *Provider) BeginAuth(ctx context.Context, state string, _ ...any) (idp.Session, error) {
- url := rp.AuthURL(state, p.RelyingParty, rp.WithPrompt(oidc.PromptSelectAccount))
+ url := rp.AuthURL(state, p.RelyingParty, p.authOptions...)
return &Session{AuthURL: url, Provider: p}, nil
}
diff --git a/internal/idp/providers/oidc/oidc_test.go b/internal/idp/providers/oidc/oidc_test.go
index 7875f241b0..71f110a658 100644
--- a/internal/idp/providers/oidc/oidc_test.go
+++ b/internal/idp/providers/oidc/oidc_test.go
@@ -23,6 +23,7 @@ func TestProvider_BeginAuth(t *testing.T) {
scopes []string
userMapper func(info oidc.UserInfo) idp.User
httpMock func(issuer string)
+ opts []ProviderOpts
}
tests := []struct {
name string
@@ -50,6 +51,7 @@ func TestProvider_BeginAuth(t *testing.T) {
UserinfoEndpoint: issuer + "/userinfo",
})
},
+ opts: []ProviderOpts{WithSelectAccount()},
},
want: &Session{AuthURL: "https://issuer.com/authorize?client_id=clientID&prompt=select_account&redirect_uri=redirectURI&response_type=code&scope=openid&state=testState"},
},
@@ -61,7 +63,7 @@ func TestProvider_BeginAuth(t *testing.T) {
a := assert.New(t)
r := require.New(t)
- provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.userMapper)
+ provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.userMapper, tt.fields.opts...)
r.NoError(err)
session, err := provider.BeginAuth(context.Background(), "testState")
diff --git a/internal/query/idp_template.go b/internal/query/idp_template.go
index e954e1e483..098cf4b749 100644
--- a/internal/query/idp_template.go
+++ b/internal/query/idp_template.go
@@ -39,6 +39,8 @@ type IDPTemplate struct {
*JWTIDPTemplate
*GitHubIDPTemplate
*GitHubEnterpriseIDPTemplate
+ *GitLabIDPTemplate
+ *GitLabSelfHostedIDPTemplate
*GoogleIDPTemplate
*LDAPIDPTemplate
}
@@ -92,6 +94,21 @@ type GitHubEnterpriseIDPTemplate struct {
Scopes database.StringArray
}
+type GitLabIDPTemplate struct {
+ IDPID string
+ ClientID string
+ ClientSecret *crypto.CryptoValue
+ Scopes database.StringArray
+}
+
+type GitLabSelfHostedIDPTemplate struct {
+ IDPID string
+ Issuer string
+ ClientID string
+ ClientSecret *crypto.CryptoValue
+ Scopes database.StringArray
+}
+
type GoogleIDPTemplate struct {
IDPID string
ClientID string
@@ -350,6 +367,64 @@ var (
}
)
+var (
+ gitlabIdpTemplateTable = table{
+ name: projection.IDPTemplateGitLabTable,
+ instanceIDCol: projection.GitLabInstanceIDCol,
+ }
+ GitLabIDCol = Column{
+ name: projection.GitLabIDCol,
+ table: gitlabIdpTemplateTable,
+ }
+ GitLabInstanceIDCol = Column{
+ name: projection.GitLabInstanceIDCol,
+ table: gitlabIdpTemplateTable,
+ }
+ GitLabClientIDCol = Column{
+ name: projection.GitLabClientIDCol,
+ table: gitlabIdpTemplateTable,
+ }
+ GitLabClientSecretCol = Column{
+ name: projection.GitLabClientSecretCol,
+ table: gitlabIdpTemplateTable,
+ }
+ GitLabScopesCol = Column{
+ name: projection.GitLabScopesCol,
+ table: gitlabIdpTemplateTable,
+ }
+)
+
+var (
+ gitlabSelfHostedIdpTemplateTable = table{
+ name: projection.IDPTemplateGitLabSelfHostedTable,
+ instanceIDCol: projection.GitLabSelfHostedInstanceIDCol,
+ }
+ GitLabSelfHostedIDCol = Column{
+ name: projection.GitLabSelfHostedIDCol,
+ table: gitlabSelfHostedIdpTemplateTable,
+ }
+ GitLabSelfHostedInstanceIDCol = Column{
+ name: projection.GitLabSelfHostedInstanceIDCol,
+ table: gitlabSelfHostedIdpTemplateTable,
+ }
+ GitLabSelfHostedIssuerCol = Column{
+ name: projection.GitLabSelfHostedIssuerCol,
+ table: gitlabSelfHostedIdpTemplateTable,
+ }
+ GitLabSelfHostedClientIDCol = Column{
+ name: projection.GitLabSelfHostedClientIDCol,
+ table: gitlabSelfHostedIdpTemplateTable,
+ }
+ GitLabSelfHostedClientSecretCol = Column{
+ name: projection.GitLabSelfHostedClientSecretCol,
+ table: gitlabSelfHostedIdpTemplateTable,
+ }
+ GitLabSelfHostedScopesCol = Column{
+ name: projection.GitLabSelfHostedScopesCol,
+ table: gitlabSelfHostedIdpTemplateTable,
+ }
+)
+
var (
googleIdpTemplateTable = table{
name: projection.IDPTemplateGoogleTable,
@@ -621,6 +696,17 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
GitHubEnterpriseTokenEndpointCol.identifier(),
GitHubEnterpriseUserEndpointCol.identifier(),
GitHubEnterpriseScopesCol.identifier(),
+ // gitlab
+ GitLabIDCol.identifier(),
+ GitLabClientIDCol.identifier(),
+ GitLabClientSecretCol.identifier(),
+ GitLabScopesCol.identifier(),
+ // gitlab self hosted
+ GitLabSelfHostedIDCol.identifier(),
+ GitLabSelfHostedIssuerCol.identifier(),
+ GitLabSelfHostedClientIDCol.identifier(),
+ GitLabSelfHostedClientSecretCol.identifier(),
+ GitLabSelfHostedScopesCol.identifier(),
// google
GoogleIDCol.identifier(),
GoogleClientIDCol.identifier(),
@@ -655,6 +741,8 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
LeftJoin(join(GitHubIDCol, IDPTemplateIDCol)).
LeftJoin(join(GitHubEnterpriseIDCol, IDPTemplateIDCol)).
+ LeftJoin(join(GitLabIDCol, IDPTemplateIDCol)).
+ LeftJoin(join(GitLabSelfHostedIDCol, IDPTemplateIDCol)).
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
@@ -697,6 +785,17 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
githubEnterpriseUserEndpoint := sql.NullString{}
githubEnterpriseScopes := database.StringArray{}
+ gitlabID := sql.NullString{}
+ gitlabClientID := sql.NullString{}
+ gitlabClientSecret := new(crypto.CryptoValue)
+ gitlabScopes := database.StringArray{}
+
+ gitlabSelfHostedID := sql.NullString{}
+ gitlabSelfHostedIssuer := sql.NullString{}
+ gitlabSelfHostedClientID := sql.NullString{}
+ gitlabSelfHostedClientSecret := new(crypto.CryptoValue)
+ gitlabSelfHostedScopes := database.StringArray{}
+
googleID := sql.NullString{}
googleClientID := sql.NullString{}
googleClientSecret := new(crypto.CryptoValue)
@@ -773,6 +872,17 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
&githubEnterpriseTokenEndpoint,
&githubEnterpriseUserEndpoint,
&githubEnterpriseScopes,
+ // gitlab
+ &gitlabID,
+ &gitlabClientID,
+ &gitlabClientSecret,
+ &gitlabScopes,
+ // gitlab self hosted
+ &gitlabSelfHostedID,
+ &gitlabSelfHostedIssuer,
+ &gitlabSelfHostedClientID,
+ &gitlabSelfHostedClientSecret,
+ &gitlabSelfHostedScopes,
// google
&googleID,
&googleClientID,
@@ -860,6 +970,23 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
Scopes: githubEnterpriseScopes,
}
}
+ if gitlabID.Valid {
+ idpTemplate.GitLabIDPTemplate = &GitLabIDPTemplate{
+ IDPID: gitlabID.String,
+ ClientID: gitlabClientID.String,
+ ClientSecret: gitlabClientSecret,
+ Scopes: gitlabScopes,
+ }
+ }
+ if gitlabSelfHostedID.Valid {
+ idpTemplate.GitLabSelfHostedIDPTemplate = &GitLabSelfHostedIDPTemplate{
+ IDPID: gitlabSelfHostedID.String,
+ Issuer: gitlabSelfHostedIssuer.String,
+ ClientID: gitlabSelfHostedClientID.String,
+ ClientSecret: gitlabSelfHostedClientSecret,
+ Scopes: gitlabSelfHostedScopes,
+ }
+ }
if googleID.Valid {
idpTemplate.GoogleIDPTemplate = &GoogleIDPTemplate{
IDPID: googleID.String,
@@ -950,6 +1077,17 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
GitHubEnterpriseTokenEndpointCol.identifier(),
GitHubEnterpriseUserEndpointCol.identifier(),
GitHubEnterpriseScopesCol.identifier(),
+ // gitlab
+ GitLabIDCol.identifier(),
+ GitLabClientIDCol.identifier(),
+ GitLabClientSecretCol.identifier(),
+ GitLabScopesCol.identifier(),
+ // gitlab self hosted
+ GitLabSelfHostedIDCol.identifier(),
+ GitLabSelfHostedIssuerCol.identifier(),
+ GitLabSelfHostedClientIDCol.identifier(),
+ GitLabSelfHostedClientSecretCol.identifier(),
+ GitLabSelfHostedScopesCol.identifier(),
// google
GoogleIDCol.identifier(),
GoogleClientIDCol.identifier(),
@@ -985,6 +1123,8 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
LeftJoin(join(GitHubIDCol, IDPTemplateIDCol)).
LeftJoin(join(GitHubEnterpriseIDCol, IDPTemplateIDCol)).
+ LeftJoin(join(GitLabIDCol, IDPTemplateIDCol)).
+ LeftJoin(join(GitLabSelfHostedIDCol, IDPTemplateIDCol)).
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
@@ -1030,6 +1170,17 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
githubEnterpriseUserEndpoint := sql.NullString{}
githubEnterpriseScopes := database.StringArray{}
+ gitlabID := sql.NullString{}
+ gitlabClientID := sql.NullString{}
+ gitlabClientSecret := new(crypto.CryptoValue)
+ gitlabScopes := database.StringArray{}
+
+ gitlabSelfHostedID := sql.NullString{}
+ gitlabSelfHostedIssuer := sql.NullString{}
+ gitlabSelfHostedClientID := sql.NullString{}
+ gitlabSelfHostedClientSecret := new(crypto.CryptoValue)
+ gitlabSelfHostedScopes := database.StringArray{}
+
googleID := sql.NullString{}
googleClientID := sql.NullString{}
googleClientSecret := new(crypto.CryptoValue)
@@ -1106,6 +1257,17 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
&githubEnterpriseTokenEndpoint,
&githubEnterpriseUserEndpoint,
&githubEnterpriseScopes,
+ // gitlab
+ &gitlabID,
+ &gitlabClientID,
+ &gitlabClientSecret,
+ &gitlabScopes,
+ // gitlab self hosted
+ &gitlabSelfHostedID,
+ &gitlabSelfHostedIssuer,
+ &gitlabSelfHostedClientID,
+ &gitlabSelfHostedClientSecret,
+ &gitlabSelfHostedScopes,
// google
&googleID,
&googleClientID,
@@ -1192,6 +1354,23 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
Scopes: githubEnterpriseScopes,
}
}
+ if gitlabID.Valid {
+ idpTemplate.GitLabIDPTemplate = &GitLabIDPTemplate{
+ IDPID: gitlabID.String,
+ ClientID: gitlabClientID.String,
+ ClientSecret: gitlabClientSecret,
+ Scopes: gitlabScopes,
+ }
+ }
+ if gitlabSelfHostedID.Valid {
+ idpTemplate.GitLabSelfHostedIDPTemplate = &GitLabSelfHostedIDPTemplate{
+ IDPID: gitlabSelfHostedID.String,
+ Issuer: gitlabSelfHostedIssuer.String,
+ ClientID: gitlabSelfHostedClientID.String,
+ ClientSecret: gitlabSelfHostedClientSecret,
+ Scopes: gitlabSelfHostedScopes,
+ }
+ }
if googleID.Valid {
idpTemplate.GoogleIDPTemplate = &GoogleIDPTemplate{
IDPID: googleID.String,
diff --git a/internal/query/idp_template_test.go b/internal/query/idp_template_test.go
index cf59d153ce..aab57dfdb4 100644
--- a/internal/query/idp_template_test.go
+++ b/internal/query/idp_template_test.go
@@ -62,6 +62,17 @@ var (
` projections.idp_templates3_github_enterprise.token_endpoint,` +
` projections.idp_templates3_github_enterprise.user_endpoint,` +
` projections.idp_templates3_github_enterprise.scopes,` +
+ // gitlab
+ ` projections.idp_templates3_gitlab.idp_id,` +
+ ` projections.idp_templates3_gitlab.client_id,` +
+ ` projections.idp_templates3_gitlab.client_secret,` +
+ ` projections.idp_templates3_gitlab.scopes,` +
+ // gitlab self hosted
+ ` projections.idp_templates3_gitlab_self_hosted.idp_id,` +
+ ` projections.idp_templates3_gitlab_self_hosted.issuer,` +
+ ` projections.idp_templates3_gitlab_self_hosted.client_id,` +
+ ` projections.idp_templates3_gitlab_self_hosted.client_secret,` +
+ ` projections.idp_templates3_gitlab_self_hosted.scopes,` +
// google
` projections.idp_templates3_google.idp_id,` +
` projections.idp_templates3_google.client_id,` +
@@ -96,6 +107,8 @@ var (
` LEFT JOIN projections.idp_templates3_jwt ON projections.idp_templates3.id = projections.idp_templates3_jwt.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_jwt.instance_id` +
` LEFT JOIN projections.idp_templates3_github ON projections.idp_templates3.id = projections.idp_templates3_github.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github.instance_id` +
` LEFT JOIN projections.idp_templates3_github_enterprise ON projections.idp_templates3.id = projections.idp_templates3_github_enterprise.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github_enterprise.instance_id` +
+ ` LEFT JOIN projections.idp_templates3_gitlab ON projections.idp_templates3.id = projections.idp_templates3_gitlab.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab.instance_id` +
+ ` LEFT JOIN projections.idp_templates3_gitlab_self_hosted ON projections.idp_templates3.id = projections.idp_templates3_gitlab_self_hosted.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab_self_hosted.instance_id` +
` LEFT JOIN projections.idp_templates3_google ON projections.idp_templates3.id = projections.idp_templates3_google.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_google.instance_id` +
` LEFT JOIN projections.idp_templates3_ldap ON projections.idp_templates3.id = projections.idp_templates3_ldap.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_ldap.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
@@ -147,6 +160,17 @@ var (
"token_endpoint",
"user_endpoint",
"scopes",
+ // gitlab config
+ "idp_id",
+ "client_id",
+ "client_secret",
+ "scopes",
+ // gitlab self hosted config
+ "idp_id",
+ "issuer",
+ "client_id",
+ "client_secret",
+ "scopes",
// google config
"idp_id",
"client_id",
@@ -223,6 +247,17 @@ var (
` projections.idp_templates3_github_enterprise.token_endpoint,` +
` projections.idp_templates3_github_enterprise.user_endpoint,` +
` projections.idp_templates3_github_enterprise.scopes,` +
+ // gitlab
+ ` projections.idp_templates3_gitlab.idp_id,` +
+ ` projections.idp_templates3_gitlab.client_id,` +
+ ` projections.idp_templates3_gitlab.client_secret,` +
+ ` projections.idp_templates3_gitlab.scopes,` +
+ // gitlab self hosted
+ ` projections.idp_templates3_gitlab_self_hosted.idp_id,` +
+ ` projections.idp_templates3_gitlab_self_hosted.issuer,` +
+ ` projections.idp_templates3_gitlab_self_hosted.client_id,` +
+ ` projections.idp_templates3_gitlab_self_hosted.client_secret,` +
+ ` projections.idp_templates3_gitlab_self_hosted.scopes,` +
// google
` projections.idp_templates3_google.idp_id,` +
` projections.idp_templates3_google.client_id,` +
@@ -258,6 +293,8 @@ var (
` LEFT JOIN projections.idp_templates3_jwt ON projections.idp_templates3.id = projections.idp_templates3_jwt.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_jwt.instance_id` +
` LEFT JOIN projections.idp_templates3_github ON projections.idp_templates3.id = projections.idp_templates3_github.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github.instance_id` +
` LEFT JOIN projections.idp_templates3_github_enterprise ON projections.idp_templates3.id = projections.idp_templates3_github_enterprise.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github_enterprise.instance_id` +
+ ` LEFT JOIN projections.idp_templates3_gitlab ON projections.idp_templates3.id = projections.idp_templates3_gitlab.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab.instance_id` +
+ ` LEFT JOIN projections.idp_templates3_gitlab_self_hosted ON projections.idp_templates3.id = projections.idp_templates3_gitlab_self_hosted.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab_self_hosted.instance_id` +
` LEFT JOIN projections.idp_templates3_google ON projections.idp_templates3.id = projections.idp_templates3_google.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_google.instance_id` +
` LEFT JOIN projections.idp_templates3_ldap ON projections.idp_templates3.id = projections.idp_templates3_ldap.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_ldap.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
@@ -309,6 +346,17 @@ var (
"token_endpoint",
"user_endpoint",
"scopes",
+ // gitlab config
+ "idp_id",
+ "client_id",
+ "client_secret",
+ "scopes",
+ // gitlab self hosted config
+ "idp_id",
+ "issuer",
+ "client_id",
+ "client_secret",
+ "scopes",
// google config
"idp_id",
"client_id",
@@ -425,6 +473,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
@@ -537,6 +596,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
@@ -646,6 +716,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
@@ -755,6 +836,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
@@ -808,6 +900,245 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
},
},
},
+ {
+ name: "prepareIDPTemplateByIDQuery gitlab idp",
+ prepare: prepareIDPTemplateByIDQuery,
+ want: want{
+ sqlExpectations: mockQuery(
+ regexp.QuoteMeta(idpTemplateQuery),
+ idpTemplateCols,
+ []driver.Value{
+ "idp-id",
+ "ro",
+ testNow,
+ testNow,
+ uint64(20211109),
+ domain.IDPConfigStateActive,
+ "idp-name",
+ domain.IDPTypeGitLab,
+ domain.IdentityProviderTypeOrg,
+ true,
+ true,
+ true,
+ true,
+ // oauth
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // oidc
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // jwt
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // github
+ nil,
+ nil,
+ nil,
+ nil,
+ // github enterprise
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab
+ "idp-id",
+ "client_id",
+ nil,
+ database.StringArray{"profile"},
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // google
+ nil,
+ nil,
+ nil,
+ nil,
+ // ldap config
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ },
+ ),
+ },
+ object: &IDPTemplate{
+ CreationDate: testNow,
+ ChangeDate: testNow,
+ Sequence: 20211109,
+ ResourceOwner: "ro",
+ ID: "idp-id",
+ State: domain.IDPStateActive,
+ Name: "idp-name",
+ Type: domain.IDPTypeGitLab,
+ OwnerType: domain.IdentityProviderTypeOrg,
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ GitLabIDPTemplate: &GitLabIDPTemplate{
+ IDPID: "idp-id",
+ ClientID: "client_id",
+ ClientSecret: nil,
+ Scopes: []string{"profile"},
+ },
+ },
+ },
+ {
+ name: "prepareIDPTemplateByIDQuery gitlab self hosted idp",
+ prepare: prepareIDPTemplateByIDQuery,
+ want: want{
+ sqlExpectations: mockQuery(
+ regexp.QuoteMeta(idpTemplateQuery),
+ idpTemplateCols,
+ []driver.Value{
+ "idp-id",
+ "ro",
+ testNow,
+ testNow,
+ uint64(20211109),
+ domain.IDPConfigStateActive,
+ "idp-name",
+ domain.IDPTypeGitLabSelfHosted,
+ domain.IdentityProviderTypeOrg,
+ true,
+ true,
+ true,
+ true,
+ // oauth
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // oidc
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // jwt
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // github
+ nil,
+ nil,
+ nil,
+ nil,
+ // github enterprise
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ "idp-id",
+ "issuer",
+ "client_id",
+ nil,
+ database.StringArray{"profile"},
+ // google
+ nil,
+ nil,
+ nil,
+ nil,
+ // ldap config
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ },
+ ),
+ },
+ object: &IDPTemplate{
+ CreationDate: testNow,
+ ChangeDate: testNow,
+ Sequence: 20211109,
+ ResourceOwner: "ro",
+ ID: "idp-id",
+ State: domain.IDPStateActive,
+ Name: "idp-name",
+ Type: domain.IDPTypeGitLabSelfHosted,
+ OwnerType: domain.IdentityProviderTypeOrg,
+ IsCreationAllowed: true,
+ IsLinkingAllowed: true,
+ IsAutoCreation: true,
+ IsAutoUpdate: true,
+ GitLabSelfHostedIDPTemplate: &GitLabSelfHostedIDPTemplate{
+ IDPID: "idp-id",
+ Issuer: "issuer",
+ ClientID: "client_id",
+ ClientSecret: nil,
+ Scopes: []string{"profile"},
+ },
+ },
+ },
{
name: "prepareIDPTemplateByIDQuery google idp",
prepare: prepareIDPTemplateByIDQuery,
@@ -863,6 +1194,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
"idp-id",
"client_id",
@@ -971,6 +1313,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
@@ -1098,6 +1451,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google config
nil,
nil,
@@ -1236,6 +1600,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google config
nil,
nil,
@@ -1372,6 +1747,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google config
nil,
nil,
@@ -1483,6 +1869,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google config
nil,
nil,
@@ -1560,6 +1957,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
"idp-id-google",
"client_id",
@@ -1637,6 +2045,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
@@ -1714,6 +2133,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
@@ -1791,6 +2221,17 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
+ // gitlab
+ nil,
+ nil,
+ nil,
+ nil,
+ // gitlab self hosted
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
// google
nil,
nil,
diff --git a/internal/query/projection/idp_template.go b/internal/query/projection/idp_template.go
index b90ee12076..59217b4352 100644
--- a/internal/query/projection/idp_template.go
+++ b/internal/query/projection/idp_template.go
@@ -17,22 +17,26 @@ import (
)
const (
- IDPTemplateTable = "projections.idp_templates3"
- IDPTemplateOAuthTable = IDPTemplateTable + "_" + IDPTemplateOAuthSuffix
- IDPTemplateOIDCTable = IDPTemplateTable + "_" + IDPTemplateOIDCSuffix
- IDPTemplateJWTTable = IDPTemplateTable + "_" + IDPTemplateJWTSuffix
+ IDPTemplateTable = "projections.idp_templates3"
+ IDPTemplateOAuthTable = IDPTemplateTable + "_" + IDPTemplateOAuthSuffix
+ IDPTemplateOIDCTable = IDPTemplateTable + "_" + IDPTemplateOIDCSuffix
+ IDPTemplateJWTTable = IDPTemplateTable + "_" + IDPTemplateJWTSuffix
IDPTemplateGitHubTable = IDPTemplateTable + "_" + IDPTemplateGitHubSuffix
IDPTemplateGitHubEnterpriseTable = IDPTemplateTable + "_" + IDPTemplateGitHubEnterpriseSuffix
- IDPTemplateGoogleTable = IDPTemplateTable + "_" + IDPTemplateGoogleSuffix
- IDPTemplateLDAPTable = IDPTemplateTable + "_" + IDPTemplateLDAPSuffix
+ IDPTemplateGitLabTable = IDPTemplateTable + "_" + IDPTemplateGitLabSuffix
+ IDPTemplateGitLabSelfHostedTable = IDPTemplateTable + "_" + IDPTemplateGitLabSelfHostedSuffix
+ IDPTemplateGoogleTable = IDPTemplateTable + "_" + IDPTemplateGoogleSuffix
+ IDPTemplateLDAPTable = IDPTemplateTable + "_" + IDPTemplateLDAPSuffix
- IDPTemplateOAuthSuffix = "oauth2"
- IDPTemplateOIDCSuffix = "oidc"
- IDPTemplateJWTSuffix = "jwt"
+ IDPTemplateOAuthSuffix = "oauth2"
+ IDPTemplateOIDCSuffix = "oidc"
+ IDPTemplateJWTSuffix = "jwt"
IDPTemplateGitHubSuffix = "github"
IDPTemplateGitHubEnterpriseSuffix = "github_enterprise"
- IDPTemplateGoogleSuffix = "google"
- IDPTemplateLDAPSuffix = "ldap"
+ IDPTemplateGitLabSuffix = "gitlab"
+ IDPTemplateGitLabSelfHostedSuffix = "gitlab_self_hosted"
+ IDPTemplateGoogleSuffix = "google"
+ IDPTemplateLDAPSuffix = "ldap"
IDPTemplateIDCol = "id"
IDPTemplateCreationDateCol = "creation_date"
@@ -89,6 +93,19 @@ const (
GitHubEnterpriseUserEndpointCol = "user_endpoint"
GitHubEnterpriseScopesCol = "scopes"
+ GitLabIDCol = "idp_id"
+ GitLabInstanceIDCol = "instance_id"
+ GitLabClientIDCol = "client_id"
+ GitLabClientSecretCol = "client_secret"
+ GitLabScopesCol = "scopes"
+
+ GitLabSelfHostedIDCol = "idp_id"
+ GitLabSelfHostedInstanceIDCol = "instance_id"
+ GitLabSelfHostedIssuerCol = "issuer"
+ GitLabSelfHostedClientIDCol = "client_id"
+ GitLabSelfHostedClientSecretCol = "client_secret"
+ GitLabSelfHostedScopesCol = "scopes"
+
GoogleIDCol = "idp_id"
GoogleInstanceIDCol = "instance_id"
GoogleClientIDCol = "client_id"
@@ -214,6 +231,29 @@ func newIDPTemplateProjection(ctx context.Context, config crdb.StatementHandlerC
IDPTemplateGitHubEnterpriseSuffix,
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys()),
),
+ crdb.NewSuffixedTable([]*crdb.Column{
+ crdb.NewColumn(GitLabIDCol, crdb.ColumnTypeText),
+ crdb.NewColumn(GitLabInstanceIDCol, crdb.ColumnTypeText),
+ crdb.NewColumn(GitLabClientIDCol, crdb.ColumnTypeText),
+ crdb.NewColumn(GitLabClientSecretCol, crdb.ColumnTypeJSONB),
+ crdb.NewColumn(GitLabScopesCol, crdb.ColumnTypeTextArray, crdb.Nullable()),
+ },
+ crdb.NewPrimaryKey(GitLabInstanceIDCol, GitLabIDCol),
+ IDPTemplateGitLabSuffix,
+ crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys()),
+ ),
+ crdb.NewSuffixedTable([]*crdb.Column{
+ crdb.NewColumn(GitLabSelfHostedIDCol, crdb.ColumnTypeText),
+ crdb.NewColumn(GitLabSelfHostedInstanceIDCol, crdb.ColumnTypeText),
+ crdb.NewColumn(GitLabSelfHostedIssuerCol, crdb.ColumnTypeText),
+ crdb.NewColumn(GitLabSelfHostedClientIDCol, crdb.ColumnTypeText),
+ crdb.NewColumn(GitLabSelfHostedClientSecretCol, crdb.ColumnTypeJSONB),
+ crdb.NewColumn(GitLabSelfHostedScopesCol, crdb.ColumnTypeTextArray, crdb.Nullable()),
+ },
+ crdb.NewPrimaryKey(GitLabSelfHostedInstanceIDCol, GitLabSelfHostedIDCol),
+ IDPTemplateGitLabSelfHostedSuffix,
+ crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys()),
+ ),
crdb.NewSuffixedTable([]*crdb.Column{
crdb.NewColumn(GoogleIDCol, crdb.ColumnTypeText),
crdb.NewColumn(GoogleInstanceIDCol, crdb.ColumnTypeText),
@@ -328,6 +368,22 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
Event: instance.GitHubEnterpriseIDPChangedEventType,
Reduce: p.reduceGitHubEnterpriseIDPChanged,
},
+ {
+ Event: instance.GitLabIDPAddedEventType,
+ Reduce: p.reduceGitLabIDPAdded,
+ },
+ {
+ Event: instance.GitLabIDPChangedEventType,
+ Reduce: p.reduceGitLabIDPChanged,
+ },
+ {
+ Event: instance.GitLabSelfHostedIDPAddedEventType,
+ Reduce: p.reduceGitLabSelfHostedIDPAdded,
+ },
+ {
+ Event: instance.GitLabSelfHostedIDPChangedEventType,
+ Reduce: p.reduceGitLabSelfHostedIDPChanged,
+ },
{
Event: instance.GoogleIDPAddedEventType,
Reduce: p.reduceGoogleIDPAdded,
@@ -422,6 +478,22 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
Event: org.GitHubEnterpriseIDPChangedEventType,
Reduce: p.reduceGitHubEnterpriseIDPChanged,
},
+ {
+ Event: org.GitLabIDPAddedEventType,
+ Reduce: p.reduceGitLabIDPAdded,
+ },
+ {
+ Event: org.GitLabIDPChangedEventType,
+ Reduce: p.reduceGitLabIDPChanged,
+ },
+ {
+ Event: org.GitLabSelfHostedIDPAddedEventType,
+ Reduce: p.reduceGitLabSelfHostedIDPAdded,
+ },
+ {
+ Event: org.GitLabSelfHostedIDPChangedEventType,
+ Reduce: p.reduceGitLabSelfHostedIDPChanged,
+ },
{
Event: org.GoogleIDPAddedEventType,
Reduce: p.reduceGoogleIDPAdded,
@@ -1156,6 +1228,183 @@ func (p *idpTemplateProjection) reduceGitHubEnterpriseIDPChanged(event eventstor
), nil
}
+func (p *idpTemplateProjection) reduceGitLabIDPAdded(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.GitLabIDPAddedEvent
+ var idpOwnerType domain.IdentityProviderType
+ switch e := event.(type) {
+ case *org.GitLabIDPAddedEvent:
+ idpEvent = e.GitLabIDPAddedEvent
+ idpOwnerType = domain.IdentityProviderTypeOrg
+ case *instance.GitLabIDPAddedEvent:
+ idpEvent = e.GitLabIDPAddedEvent
+ idpOwnerType = domain.IdentityProviderTypeSystem
+ default:
+ return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-x9a022b", "reduce.wrong.event.type %v", []eventstore.EventType{org.GitLabIDPAddedEventType, instance.GitLabIDPAddedEventType})
+ }
+
+ return crdb.NewMultiStatement(
+ &idpEvent,
+ crdb.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.IDPTypeGitLab),
+ handler.NewCol(IDPTemplateIsCreationAllowedCol, idpEvent.IsCreationAllowed),
+ handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
+ handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
+ handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
+ },
+ ),
+ crdb.AddCreateStatement(
+ []handler.Column{
+ handler.NewCol(GitLabIDCol, idpEvent.ID),
+ handler.NewCol(GitLabInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ handler.NewCol(GitLabClientIDCol, idpEvent.ClientID),
+ handler.NewCol(GitLabClientSecretCol, idpEvent.ClientSecret),
+ handler.NewCol(GitLabScopesCol, database.StringArray(idpEvent.Scopes)),
+ },
+ crdb.WithTableSuffix(IDPTemplateGitLabSuffix),
+ ),
+ ), nil
+}
+
+func (p *idpTemplateProjection) reduceGitLabIDPChanged(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.GitLabIDPChangedEvent
+ switch e := event.(type) {
+ case *org.GitLabIDPChangedEvent:
+ idpEvent = e.GitLabIDPChangedEvent
+ case *instance.GitLabIDPChangedEvent:
+ idpEvent = e.GitLabIDPChangedEvent
+ default:
+ return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-p1582ks", "reduce.wrong.event.type %v", []eventstore.EventType{org.GitLabIDPChangedEventType, instance.GitLabIDPChangedEventType})
+ }
+
+ ops := make([]func(eventstore.Event) crdb.Exec, 0, 2)
+ ops = append(ops,
+ crdb.AddUpdateStatement(
+ reduceIDPChangedTemplateColumns(idpEvent.Name, idpEvent.CreationDate(), idpEvent.Sequence(), idpEvent.OptionChanges),
+ []handler.Condition{
+ handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
+ handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ },
+ ),
+ )
+ gitlabCols := reduceGitLabIDPChangedColumns(idpEvent)
+ if len(gitlabCols) > 0 {
+ ops = append(ops,
+ crdb.AddUpdateStatement(
+ gitlabCols,
+ []handler.Condition{
+ handler.NewCond(GitLabIDCol, idpEvent.ID),
+ handler.NewCond(GitLabInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ },
+ crdb.WithTableSuffix(IDPTemplateGitLabSuffix),
+ ),
+ )
+ }
+
+ return crdb.NewMultiStatement(
+ &idpEvent,
+ ops...,
+ ), nil
+}
+
+func (p *idpTemplateProjection) reduceGitLabSelfHostedIDPAdded(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.GitLabSelfHostedIDPAddedEvent
+ var idpOwnerType domain.IdentityProviderType
+ switch e := event.(type) {
+ case *org.GitLabSelfHostedIDPAddedEvent:
+ idpEvent = e.GitLabSelfHostedIDPAddedEvent
+ idpOwnerType = domain.IdentityProviderTypeOrg
+ case *instance.GitLabSelfHostedIDPAddedEvent:
+ idpEvent = e.GitLabSelfHostedIDPAddedEvent
+ idpOwnerType = domain.IdentityProviderTypeSystem
+ default:
+ return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-SAF3gw", "reduce.wrong.event.type %v", []eventstore.EventType{org.GitLabSelfHostedIDPAddedEventType, instance.GitLabSelfHostedIDPAddedEventType})
+ }
+
+ return crdb.NewMultiStatement(
+ &idpEvent,
+ crdb.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.IDPTypeGitLabSelfHosted),
+ handler.NewCol(IDPTemplateIsCreationAllowedCol, idpEvent.IsCreationAllowed),
+ handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
+ handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
+ handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
+ },
+ ),
+ crdb.AddCreateStatement(
+ []handler.Column{
+ handler.NewCol(GitLabSelfHostedIDCol, idpEvent.ID),
+ handler.NewCol(GitLabSelfHostedInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ handler.NewCol(GitLabSelfHostedIssuerCol, idpEvent.Issuer),
+ handler.NewCol(GitLabSelfHostedClientIDCol, idpEvent.ClientID),
+ handler.NewCol(GitLabSelfHostedClientSecretCol, idpEvent.ClientSecret),
+ handler.NewCol(GitLabSelfHostedScopesCol, database.StringArray(idpEvent.Scopes)),
+ },
+ crdb.WithTableSuffix(IDPTemplateGitLabSelfHostedSuffix),
+ ),
+ ), nil
+}
+
+func (p *idpTemplateProjection) reduceGitLabSelfHostedIDPChanged(event eventstore.Event) (*handler.Statement, error) {
+ var idpEvent idp.GitLabSelfHostedIDPChangedEvent
+ switch e := event.(type) {
+ case *org.GitLabSelfHostedIDPChangedEvent:
+ idpEvent = e.GitLabSelfHostedIDPChangedEvent
+ case *instance.GitLabSelfHostedIDPChangedEvent:
+ idpEvent = e.GitLabSelfHostedIDPChangedEvent
+ default:
+ return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-SAf3g2", "reduce.wrong.event.type %v", []eventstore.EventType{org.GitLabSelfHostedIDPChangedEventType, instance.GitLabSelfHostedIDPChangedEventType})
+ }
+
+ ops := make([]func(eventstore.Event) crdb.Exec, 0, 2)
+ ops = append(ops,
+ crdb.AddUpdateStatement(
+ reduceIDPChangedTemplateColumns(idpEvent.Name, idpEvent.CreationDate(), idpEvent.Sequence(), idpEvent.OptionChanges),
+ []handler.Condition{
+ handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
+ handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ },
+ ),
+ )
+ gitlabCols := reduceGitLabSelfHostedIDPChangedColumns(idpEvent)
+ if len(gitlabCols) > 0 {
+ ops = append(ops,
+ crdb.AddUpdateStatement(
+ gitlabCols,
+ []handler.Condition{
+ handler.NewCond(GitLabSelfHostedIDCol, idpEvent.ID),
+ handler.NewCond(GitLabSelfHostedInstanceIDCol, idpEvent.Aggregate().InstanceID),
+ },
+ crdb.WithTableSuffix(IDPTemplateGitLabSelfHostedSuffix),
+ ),
+ )
+ }
+
+ return crdb.NewMultiStatement(
+ &idpEvent,
+ ops...,
+ ), nil
+}
+
func (p *idpTemplateProjection) reduceGoogleIDPAdded(event eventstore.Event) (*handler.Statement, error) {
var idpEvent idp.GoogleIDPAddedEvent
var idpOwnerType domain.IdentityProviderType
@@ -1511,6 +1760,37 @@ func reduceGitHubEnterpriseIDPChangedColumns(idpEvent idp.GitHubEnterpriseIDPCha
return oauthCols
}
+func reduceGitLabIDPChangedColumns(idpEvent idp.GitLabIDPChangedEvent) []handler.Column {
+ gitlabCols := make([]handler.Column, 0, 3)
+ if idpEvent.ClientID != nil {
+ gitlabCols = append(gitlabCols, handler.NewCol(GitLabClientIDCol, *idpEvent.ClientID))
+ }
+ if idpEvent.ClientSecret != nil {
+ gitlabCols = append(gitlabCols, handler.NewCol(GitLabClientSecretCol, *idpEvent.ClientSecret))
+ }
+ if idpEvent.Scopes != nil {
+ gitlabCols = append(gitlabCols, handler.NewCol(GitLabScopesCol, database.StringArray(idpEvent.Scopes)))
+ }
+ return gitlabCols
+}
+
+func reduceGitLabSelfHostedIDPChangedColumns(idpEvent idp.GitLabSelfHostedIDPChangedEvent) []handler.Column {
+ gitlabCols := make([]handler.Column, 0, 4)
+ if idpEvent.Issuer != nil {
+ gitlabCols = append(gitlabCols, handler.NewCol(GitLabSelfHostedIssuerCol, *idpEvent.Issuer))
+ }
+ if idpEvent.ClientID != nil {
+ gitlabCols = append(gitlabCols, handler.NewCol(GitLabSelfHostedClientIDCol, *idpEvent.ClientID))
+ }
+ if idpEvent.ClientSecret != nil {
+ gitlabCols = append(gitlabCols, handler.NewCol(GitLabSelfHostedClientSecretCol, *idpEvent.ClientSecret))
+ }
+ if idpEvent.Scopes != nil {
+ gitlabCols = append(gitlabCols, handler.NewCol(GitLabSelfHostedScopesCol, database.StringArray(idpEvent.Scopes)))
+ }
+ return gitlabCols
+}
+
func reduceGoogleIDPChangedColumns(idpEvent idp.GoogleIDPChangedEvent) []handler.Column {
googleCols := make([]handler.Column, 0, 3)
if idpEvent.ClientID != nil {
diff --git a/internal/query/projection/idp_template_test.go b/internal/query/projection/idp_template_test.go
index 70f49932fe..00fc50cb0e 100644
--- a/internal/query/projection/idp_template_test.go
+++ b/internal/query/projection/idp_template_test.go
@@ -13,6 +13,15 @@ import (
"github.com/zitadel/zitadel/internal/repository/org"
)
+var (
+ idpTemplateInsertStmt = `INSERT INTO projections.idp_templates3` +
+ ` (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update)` +
+ ` VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)`
+ idpTemplateUpdateMinimalStmt = `UPDATE projections.idp_templates3 SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)`
+ idpTemplateUpdateStmt = `UPDATE projections.idp_templates3 SET (name, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update, change_date, sequence)` +
+ ` = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8) AND (instance_id = $9)`
+)
+
func TestIDPTemplateProjection_reducesRemove(t *testing.T) {
type args struct {
event func(t *testing.T) eventstore.Event
@@ -170,7 +179,7 @@ func TestIDPTemplateProjection_reducesOAuth(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -241,7 +250,7 @@ func TestIDPTemplateProjection_reducesOAuth(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -298,7 +307,7 @@ func TestIDPTemplateProjection_reducesOAuth(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
+ expectedStmt: idpTemplateUpdateMinimalStmt,
expectedArgs: []interface{}{
true,
anyArg{},
@@ -354,7 +363,7 @@ func TestIDPTemplateProjection_reducesOAuth(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (name, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update, change_date, sequence) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8) AND (instance_id = $9)",
+ expectedStmt: idpTemplateUpdateStmt,
expectedArgs: []interface{}{
"custom-zitadel-instance",
true,
@@ -442,7 +451,7 @@ func TestIDPTemplateProjection_reducesGitHub(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -505,7 +514,7 @@ func TestIDPTemplateProjection_reducesGitHub(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -558,7 +567,7 @@ func TestIDPTemplateProjection_reducesGitHub(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
+ expectedStmt: idpTemplateUpdateMinimalStmt,
expectedArgs: []interface{}{
true,
anyArg{},
@@ -610,7 +619,7 @@ func TestIDPTemplateProjection_reducesGitHub(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (name, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update, change_date, sequence) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8) AND (instance_id = $9)",
+ expectedStmt: idpTemplateUpdateStmt,
expectedArgs: []interface{}{
"name",
true,
@@ -697,7 +706,7 @@ func TestIDPTemplateProjection_reducesGitHubEnterprise(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -766,7 +775,7 @@ func TestIDPTemplateProjection_reducesGitHubEnterprise(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -822,7 +831,7 @@ func TestIDPTemplateProjection_reducesGitHubEnterprise(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
+ expectedStmt: idpTemplateUpdateMinimalStmt,
expectedArgs: []interface{}{
true,
anyArg{},
@@ -877,7 +886,7 @@ func TestIDPTemplateProjection_reducesGitHubEnterprise(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (name, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update, change_date, sequence) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8) AND (instance_id = $9)",
+ expectedStmt: idpTemplateUpdateStmt,
expectedArgs: []interface{}{
"name",
true,
@@ -923,6 +932,514 @@ func TestIDPTemplateProjection_reducesGitHubEnterprise(t *testing.T) {
}
}
+func TestIDPTemplateProjection_reducesGitLab(t *testing.T) {
+ type args struct {
+ event func(t *testing.T) eventstore.Event
+ }
+ tests := []struct {
+ name string
+ args args
+ reduce func(event eventstore.Event) (*handler.Statement, error)
+ want wantReduce
+ }{
+ {
+ name: "instance reduceGitLabIDPAdded",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(instance.GitLabIDPAddedEventType),
+ instance.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "client_id": "client_id",
+ "client_secret": {
+ "cryptoType": 0,
+ "algorithm": "RSA-265",
+ "keyId": "key-id"
+ },
+ "scopes": ["profile"],
+ "isCreationAllowed": true,
+ "isLinkingAllowed": true,
+ "isAutoCreation": true,
+ "isAutoUpdate": true
+}`),
+ ), instance.GitLabIDPAddedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabIDPAdded,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("instance"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateInsertStmt,
+ expectedArgs: []interface{}{
+ "idp-id",
+ anyArg{},
+ anyArg{},
+ uint64(15),
+ "ro-id",
+ "instance-id",
+ domain.IDPStateActive,
+ "",
+ domain.IdentityProviderTypeSystem,
+ domain.IDPTypeGitLab,
+ true,
+ true,
+ true,
+ true,
+ },
+ },
+ {
+ expectedStmt: "INSERT INTO projections.idp_templates3_gitlab (idp_id, instance_id, client_id, client_secret, scopes) VALUES ($1, $2, $3, $4, $5)",
+ expectedArgs: []interface{}{
+ "idp-id",
+ "instance-id",
+ "client_id",
+ anyArg{},
+ database.StringArray{"profile"},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "org reduceGitLabIDPAdded",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(org.GitLabIDPAddedEventType),
+ org.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "client_id": "client_id",
+ "client_secret": {
+ "cryptoType": 0,
+ "algorithm": "RSA-265",
+ "keyId": "key-id"
+ },
+ "scopes": ["profile"],
+ "isCreationAllowed": true,
+ "isLinkingAllowed": true,
+ "isAutoCreation": true,
+ "isAutoUpdate": true
+}`),
+ ), org.GitLabIDPAddedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabIDPAdded,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("org"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateInsertStmt,
+ expectedArgs: []interface{}{
+ "idp-id",
+ anyArg{},
+ anyArg{},
+ uint64(15),
+ "ro-id",
+ "instance-id",
+ domain.IDPStateActive,
+ "",
+ domain.IdentityProviderTypeOrg,
+ domain.IDPTypeGitLab,
+ true,
+ true,
+ true,
+ true,
+ },
+ },
+ {
+ expectedStmt: "INSERT INTO projections.idp_templates3_gitlab (idp_id, instance_id, client_id, client_secret, scopes) VALUES ($1, $2, $3, $4, $5)",
+ expectedArgs: []interface{}{
+ "idp-id",
+ "instance-id",
+ "client_id",
+ anyArg{},
+ database.StringArray{"profile"},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "instance reduceGitLabIDPChanged minimal",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(instance.GitLabIDPChangedEventType),
+ instance.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "isCreationAllowed": true,
+ "client_id": "id"
+}`),
+ ), instance.GitLabIDPChangedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabIDPChanged,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("instance"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateUpdateMinimalStmt,
+ expectedArgs: []interface{}{
+ true,
+ anyArg{},
+ uint64(15),
+ "idp-id",
+ "instance-id",
+ },
+ },
+ {
+ expectedStmt: "UPDATE projections.idp_templates3_gitlab SET client_id = $1 WHERE (idp_id = $2) AND (instance_id = $3)",
+ expectedArgs: []interface{}{
+ "id",
+ "idp-id",
+ "instance-id",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "instance reduceGitLabIDPChanged",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(instance.GitLabIDPChangedEventType),
+ instance.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "name": "name",
+ "client_id": "client_id",
+ "client_secret": {
+ "cryptoType": 0,
+ "algorithm": "RSA-265",
+ "keyId": "key-id"
+ },
+ "scopes": ["profile"],
+ "isCreationAllowed": true,
+ "isLinkingAllowed": true,
+ "isAutoCreation": true,
+ "isAutoUpdate": true
+}`),
+ ), instance.GitLabIDPChangedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabIDPChanged,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("instance"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateUpdateStmt,
+ expectedArgs: []interface{}{
+ "name",
+ true,
+ true,
+ true,
+ true,
+ anyArg{},
+ uint64(15),
+ "idp-id",
+ "instance-id",
+ },
+ },
+ {
+ expectedStmt: "UPDATE projections.idp_templates3_gitlab SET (client_id, client_secret, scopes) = ($1, $2, $3) WHERE (idp_id = $4) AND (instance_id = $5)",
+ expectedArgs: []interface{}{
+ "client_id",
+ anyArg{},
+ database.StringArray{"profile"},
+ "idp-id",
+ "instance-id",
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ event := baseEvent(t)
+ got, err := tt.reduce(event)
+ if !errors.IsErrorInvalidArgument(err) {
+ 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, IDPTemplateTable, tt.want)
+ })
+ }
+}
+
+func TestIDPTemplateProjection_reducesGitLabSelfHosted(t *testing.T) {
+ type args struct {
+ event func(t *testing.T) eventstore.Event
+ }
+ tests := []struct {
+ name string
+ args args
+ reduce func(event eventstore.Event) (*handler.Statement, error)
+ want wantReduce
+ }{
+ {
+ name: "instance reduceGitLabSelfHostedIDPAdded",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(instance.GitLabSelfHostedIDPAddedEventType),
+ instance.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "name": "name",
+ "issuer": "issuer",
+ "client_id": "client_id",
+ "client_secret": {
+ "cryptoType": 0,
+ "algorithm": "RSA-265",
+ "keyId": "key-id"
+ },
+ "scopes": ["profile"],
+ "isCreationAllowed": true,
+ "isLinkingAllowed": true,
+ "isAutoCreation": true,
+ "isAutoUpdate": true
+}`),
+ ), instance.GitLabSelfHostedIDPAddedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabSelfHostedIDPAdded,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("instance"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateInsertStmt,
+ expectedArgs: []interface{}{
+ "idp-id",
+ anyArg{},
+ anyArg{},
+ uint64(15),
+ "ro-id",
+ "instance-id",
+ domain.IDPStateActive,
+ "name",
+ domain.IdentityProviderTypeSystem,
+ domain.IDPTypeGitLabSelfHosted,
+ true,
+ true,
+ true,
+ true,
+ },
+ },
+ {
+ expectedStmt: "INSERT INTO projections.idp_templates3_gitlab_self_hosted (idp_id, instance_id, issuer, client_id, client_secret, scopes) VALUES ($1, $2, $3, $4, $5, $6)",
+ expectedArgs: []interface{}{
+ "idp-id",
+ "instance-id",
+ "issuer",
+ "client_id",
+ anyArg{},
+ database.StringArray{"profile"},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "org reduceGitLabSelfHostedIDPAdded",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(org.GitLabSelfHostedIDPAddedEventType),
+ org.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "name": "name",
+ "issuer": "issuer",
+ "client_id": "client_id",
+ "client_secret": {
+ "cryptoType": 0,
+ "algorithm": "RSA-265",
+ "keyId": "key-id"
+ },
+ "scopes": ["profile"],
+ "isCreationAllowed": true,
+ "isLinkingAllowed": true,
+ "isAutoCreation": true,
+ "isAutoUpdate": true
+}`),
+ ), org.GitLabSelfHostedIDPAddedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabSelfHostedIDPAdded,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("org"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateInsertStmt,
+ expectedArgs: []interface{}{
+ "idp-id",
+ anyArg{},
+ anyArg{},
+ uint64(15),
+ "ro-id",
+ "instance-id",
+ domain.IDPStateActive,
+ "name",
+ domain.IdentityProviderTypeOrg,
+ domain.IDPTypeGitLabSelfHosted,
+ true,
+ true,
+ true,
+ true,
+ },
+ },
+ {
+ expectedStmt: "INSERT INTO projections.idp_templates3_gitlab_self_hosted (idp_id, instance_id, issuer, client_id, client_secret, scopes) VALUES ($1, $2, $3, $4, $5, $6)",
+ expectedArgs: []interface{}{
+ "idp-id",
+ "instance-id",
+ "issuer",
+ "client_id",
+ anyArg{},
+ database.StringArray{"profile"},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "instance reduceGitLabSelfHostedIDPChanged minimal",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(instance.GitLabSelfHostedIDPChangedEventType),
+ instance.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "isCreationAllowed": true,
+ "issuer": "issuer"
+}`),
+ ), instance.GitLabSelfHostedIDPChangedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabSelfHostedIDPChanged,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("instance"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateUpdateMinimalStmt,
+ expectedArgs: []interface{}{
+ true,
+ anyArg{},
+ uint64(15),
+ "idp-id",
+ "instance-id",
+ },
+ },
+ {
+ expectedStmt: "UPDATE projections.idp_templates3_gitlab_self_hosted SET issuer = $1 WHERE (idp_id = $2) AND (instance_id = $3)",
+ expectedArgs: []interface{}{
+ "issuer",
+ "idp-id",
+ "instance-id",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "instance reduceGitLabSelfHostedIDPChanged",
+ args: args{
+ event: getEvent(testEvent(
+ repository.EventType(instance.GitLabSelfHostedIDPChangedEventType),
+ instance.AggregateType,
+ []byte(`{
+ "id": "idp-id",
+ "name": "name",
+ "issuer": "issuer",
+ "client_id": "client_id",
+ "client_secret": {
+ "cryptoType": 0,
+ "algorithm": "RSA-265",
+ "keyId": "key-id"
+ },
+ "scopes": ["profile"],
+ "isCreationAllowed": true,
+ "isLinkingAllowed": true,
+ "isAutoCreation": true,
+ "isAutoUpdate": true
+}`),
+ ), instance.GitLabSelfHostedIDPChangedEventMapper),
+ },
+ reduce: (&idpTemplateProjection{}).reduceGitLabSelfHostedIDPChanged,
+ want: wantReduce{
+ aggregateType: eventstore.AggregateType("instance"),
+ sequence: 15,
+ previousSequence: 10,
+ executer: &testExecuter{
+ executions: []execution{
+ {
+ expectedStmt: idpTemplateUpdateStmt,
+ expectedArgs: []interface{}{
+ "name",
+ true,
+ true,
+ true,
+ true,
+ anyArg{},
+ uint64(15),
+ "idp-id",
+ "instance-id",
+ },
+ },
+ {
+ expectedStmt: "UPDATE projections.idp_templates3_gitlab_self_hosted SET (issuer, client_id, client_secret, scopes) = ($1, $2, $3, $4) WHERE (idp_id = $5) AND (instance_id = $6)",
+ expectedArgs: []interface{}{
+ "issuer",
+ "client_id",
+ anyArg{},
+ database.StringArray{"profile"},
+ "idp-id",
+ "instance-id",
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ event := baseEvent(t)
+ got, err := tt.reduce(event)
+ if !errors.IsErrorInvalidArgument(err) {
+ 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, IDPTemplateTable, tt.want)
+ })
+ }
+}
+
func TestIDPTemplateProjection_reducesGoogle(t *testing.T) {
type args struct {
event func(t *testing.T) eventstore.Event
@@ -963,7 +1480,7 @@ func TestIDPTemplateProjection_reducesGoogle(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -1025,7 +1542,7 @@ func TestIDPTemplateProjection_reducesGoogle(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -1078,7 +1595,7 @@ func TestIDPTemplateProjection_reducesGoogle(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
+ expectedStmt: idpTemplateUpdateMinimalStmt,
expectedArgs: []interface{}{
true,
anyArg{},
@@ -1107,6 +1624,7 @@ func TestIDPTemplateProjection_reducesGoogle(t *testing.T) {
instance.AggregateType,
[]byte(`{
"id": "idp-id",
+ "name": "name",
"clientId": "client_id",
"clientSecret": {
"cryptoType": 0,
@@ -1129,8 +1647,9 @@ func TestIDPTemplateProjection_reducesGoogle(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update, change_date, sequence) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
+ expectedStmt: idpTemplateUpdateStmt,
expectedArgs: []interface{}{
+ "name",
true,
true,
true,
@@ -1230,7 +1749,7 @@ func TestIDPTemplateProjection_reducesLDAP(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -1329,7 +1848,7 @@ func TestIDPTemplateProjection_reducesLDAP(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -1470,7 +1989,7 @@ func TestIDPTemplateProjection_reducesLDAP(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (name, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update, change_date, sequence) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8) AND (instance_id = $9)",
+ expectedStmt: idpTemplateUpdateStmt,
expectedArgs: []interface{}{
"custom-zitadel-instance",
true,
@@ -1602,7 +2121,7 @@ func TestIDPTemplateProjection_reducesOIDC(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -1666,7 +2185,7 @@ func TestIDPTemplateProjection_reducesOIDC(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -1720,7 +2239,7 @@ func TestIDPTemplateProjection_reducesOIDC(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
+ expectedStmt: idpTemplateUpdateMinimalStmt,
expectedArgs: []interface{}{
true,
anyArg{},
@@ -1749,6 +2268,7 @@ func TestIDPTemplateProjection_reducesOIDC(t *testing.T) {
instance.AggregateType,
[]byte(`{
"id": "idp-id",
+ "name": "name",
"issuer": "issuer",
"clientId": "client_id",
"clientSecret": {
@@ -1772,8 +2292,9 @@ func TestIDPTemplateProjection_reducesOIDC(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update, change_date, sequence) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
+ expectedStmt: idpTemplateUpdateStmt,
expectedArgs: []interface{}{
+ "name",
true,
true,
true,
@@ -1848,7 +2369,7 @@ func TestIDPTemplateProjection_reducesOldConfig(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-config-id",
anyArg{},
@@ -1893,7 +2414,7 @@ func TestIDPTemplateProjection_reducesOldConfig(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-config-id",
anyArg{},
@@ -2437,7 +2958,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -2497,7 +3018,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.idp_templates3 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, owner_type, type, is_creation_allowed, is_linking_allowed, is_auto_creation, is_auto_update) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
+ expectedStmt: idpTemplateInsertStmt,
expectedArgs: []interface{}{
"idp-id",
anyArg{},
@@ -2551,7 +3072,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.idp_templates3 SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
+ expectedStmt: idpTemplateUpdateMinimalStmt,
expectedArgs: []interface{}{
true,
anyArg{},
diff --git a/internal/repository/idp/gitlab.go b/internal/repository/idp/gitlab.go
new file mode 100644
index 0000000000..78ef99c4b0
--- /dev/null
+++ b/internal/repository/idp/gitlab.go
@@ -0,0 +1,288 @@
+package idp
+
+import (
+ "encoding/json"
+
+ "github.com/zitadel/zitadel/internal/crypto"
+ "github.com/zitadel/zitadel/internal/errors"
+ "github.com/zitadel/zitadel/internal/eventstore"
+ "github.com/zitadel/zitadel/internal/eventstore/repository"
+)
+
+type GitLabIDPAddedEvent struct {
+ eventstore.BaseEvent `json:"-"`
+
+ ID string `json:"id"`
+ Name string `json:"name,omitempty"`
+ ClientID string `json:"client_id"`
+ ClientSecret *crypto.CryptoValue `json:"client_secret"`
+ Scopes []string `json:"scopes,omitempty"`
+ Options
+}
+
+func NewGitLabIDPAddedEvent(
+ base *eventstore.BaseEvent,
+ id,
+ name,
+ clientID string,
+ clientSecret *crypto.CryptoValue,
+ scopes []string,
+ options Options,
+) *GitLabIDPAddedEvent {
+ return &GitLabIDPAddedEvent{
+ BaseEvent: *base,
+ ID: id,
+ Name: name,
+ ClientID: clientID,
+ ClientSecret: clientSecret,
+ Scopes: scopes,
+ Options: options,
+ }
+}
+
+func (e *GitLabIDPAddedEvent) Data() interface{} {
+ return e
+}
+
+func (e *GitLabIDPAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
+ return nil
+}
+
+func GitLabIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e := &GitLabIDPAddedEvent{
+ BaseEvent: *eventstore.BaseEventFromRepo(event),
+ }
+
+ err := json.Unmarshal(event.Data, e)
+ if err != nil {
+ return nil, errors.ThrowInternal(err, "IDP-KLewio", "unable to unmarshal event")
+ }
+
+ return e, nil
+}
+
+type GitLabIDPChangedEvent struct {
+ eventstore.BaseEvent `json:"-"`
+
+ ID string `json:"id"`
+ Name *string `json:"name,omitempty"`
+ ClientID *string `json:"client_id,omitempty"`
+ ClientSecret *crypto.CryptoValue `json:"client_secret,omitempty"`
+ Scopes []string `json:"scopes,omitempty"`
+ OptionChanges
+}
+
+func NewGitLabIDPChangedEvent(
+ base *eventstore.BaseEvent,
+ id string,
+ changes []GitLabIDPChanges,
+) (*GitLabIDPChangedEvent, error) {
+ if len(changes) == 0 {
+ return nil, errors.ThrowPreconditionFailed(nil, "IDP-K2gje", "Errors.NoChangesFound")
+ }
+ changedEvent := &GitLabIDPChangedEvent{
+ BaseEvent: *base,
+ ID: id,
+ }
+ for _, change := range changes {
+ change(changedEvent)
+ }
+ return changedEvent, nil
+}
+
+type GitLabIDPChanges func(*GitLabIDPChangedEvent)
+
+func ChangeGitLabName(name string) func(*GitLabIDPChangedEvent) {
+ return func(e *GitLabIDPChangedEvent) {
+ e.Name = &name
+ }
+}
+
+func ChangeGitLabClientID(clientID string) func(*GitLabIDPChangedEvent) {
+ return func(e *GitLabIDPChangedEvent) {
+ e.ClientID = &clientID
+ }
+}
+
+func ChangeGitLabClientSecret(clientSecret *crypto.CryptoValue) func(*GitLabIDPChangedEvent) {
+ return func(e *GitLabIDPChangedEvent) {
+ e.ClientSecret = clientSecret
+ }
+}
+
+func ChangeGitLabScopes(scopes []string) func(*GitLabIDPChangedEvent) {
+ return func(e *GitLabIDPChangedEvent) {
+ e.Scopes = scopes
+ }
+}
+
+func ChangeGitLabOptions(options OptionChanges) func(*GitLabIDPChangedEvent) {
+ return func(e *GitLabIDPChangedEvent) {
+ e.OptionChanges = options
+ }
+}
+
+func (e *GitLabIDPChangedEvent) Data() interface{} {
+ return e
+}
+
+func (e *GitLabIDPChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
+ return nil
+}
+
+func GitLabIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e := &GitLabIDPChangedEvent{
+ BaseEvent: *eventstore.BaseEventFromRepo(event),
+ }
+
+ err := json.Unmarshal(event.Data, e)
+ if err != nil {
+ return nil, errors.ThrowInternal(err, "IDP-Sfhjk", "unable to unmarshal event")
+ }
+
+ return e, nil
+}
+
+type GitLabSelfHostedIDPAddedEvent struct {
+ eventstore.BaseEvent `json:"-"`
+
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Issuer string `json:"issuer"`
+ ClientID string `json:"client_id"`
+ ClientSecret *crypto.CryptoValue `json:"client_secret"`
+ Scopes []string `json:"scopes,omitempty"`
+ Options
+}
+
+func NewGitLabSelfHostedIDPAddedEvent(
+ base *eventstore.BaseEvent,
+ id,
+ name,
+ issuer,
+ clientID string,
+ clientSecret *crypto.CryptoValue,
+ scopes []string,
+ options Options,
+) *GitLabSelfHostedIDPAddedEvent {
+ return &GitLabSelfHostedIDPAddedEvent{
+ BaseEvent: *base,
+ ID: id,
+ Name: name,
+ Issuer: issuer,
+ ClientID: clientID,
+ ClientSecret: clientSecret,
+ Scopes: scopes,
+ Options: options,
+ }
+}
+
+func (e *GitLabSelfHostedIDPAddedEvent) Data() interface{} {
+ return e
+}
+
+func (e *GitLabSelfHostedIDPAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
+ return nil
+}
+
+func GitLabSelfHostedIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e := &GitLabSelfHostedIDPAddedEvent{
+ BaseEvent: *eventstore.BaseEventFromRepo(event),
+ }
+
+ err := json.Unmarshal(event.Data, e)
+ if err != nil {
+ return nil, errors.ThrowInternal(err, "IDP-S1efv", "unable to unmarshal event")
+ }
+
+ return e, nil
+}
+
+type GitLabSelfHostedIDPChangedEvent struct {
+ eventstore.BaseEvent `json:"-"`
+
+ ID string `json:"id"`
+ Name *string `json:"name,omitempty"`
+ Issuer *string `json:"issuer,omitempty"`
+ ClientID *string `json:"client_id,omitempty"`
+ ClientSecret *crypto.CryptoValue `json:"client_secret,omitempty"`
+ Scopes []string `json:"scopes,omitempty"`
+ OptionChanges
+}
+
+func NewGitLabSelfHostedIDPChangedEvent(
+ base *eventstore.BaseEvent,
+ id string,
+ changes []GitLabSelfHostedIDPChanges,
+) (*GitLabSelfHostedIDPChangedEvent, error) {
+ if len(changes) == 0 {
+ return nil, errors.ThrowPreconditionFailed(nil, "IDP-Dghj6", "Errors.NoChangesFound")
+ }
+ changedEvent := &GitLabSelfHostedIDPChangedEvent{
+ BaseEvent: *base,
+ ID: id,
+ }
+ for _, change := range changes {
+ change(changedEvent)
+ }
+ return changedEvent, nil
+}
+
+type GitLabSelfHostedIDPChanges func(*GitLabSelfHostedIDPChangedEvent)
+
+func ChangeGitLabSelfHostedName(name string) func(*GitLabSelfHostedIDPChangedEvent) {
+ return func(e *GitLabSelfHostedIDPChangedEvent) {
+ e.Name = &name
+ }
+}
+
+func ChangeGitLabSelfHostedIssuer(issuer string) func(*GitLabSelfHostedIDPChangedEvent) {
+ return func(e *GitLabSelfHostedIDPChangedEvent) {
+ e.Issuer = &issuer
+ }
+}
+
+func ChangeGitLabSelfHostedClientID(clientID string) func(*GitLabSelfHostedIDPChangedEvent) {
+ return func(e *GitLabSelfHostedIDPChangedEvent) {
+ e.ClientID = &clientID
+ }
+}
+
+func ChangeGitLabSelfHostedClientSecret(clientSecret *crypto.CryptoValue) func(*GitLabSelfHostedIDPChangedEvent) {
+ return func(e *GitLabSelfHostedIDPChangedEvent) {
+ e.ClientSecret = clientSecret
+ }
+}
+
+func ChangeGitLabSelfHostedScopes(scopes []string) func(*GitLabSelfHostedIDPChangedEvent) {
+ return func(e *GitLabSelfHostedIDPChangedEvent) {
+ e.Scopes = scopes
+ }
+}
+
+func ChangeGitLabSelfHostedOptions(options OptionChanges) func(*GitLabSelfHostedIDPChangedEvent) {
+ return func(e *GitLabSelfHostedIDPChangedEvent) {
+ e.OptionChanges = options
+ }
+}
+
+func (e *GitLabSelfHostedIDPChangedEvent) Data() interface{} {
+ return e
+}
+
+func (e *GitLabSelfHostedIDPChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
+ return nil
+}
+
+func GitLabSelfHostedIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e := &GitLabSelfHostedIDPChangedEvent{
+ BaseEvent: *eventstore.BaseEventFromRepo(event),
+ }
+
+ err := json.Unmarshal(event.Data, e)
+ if err != nil {
+ return nil, errors.ThrowInternal(err, "IDP-SFrhj", "unable to unmarshal event")
+ }
+
+ return e, nil
+}
diff --git a/internal/repository/instance/eventstore.go b/internal/repository/instance/eventstore.go
index 50c430ac75..60417121e8 100644
--- a/internal/repository/instance/eventstore.go
+++ b/internal/repository/instance/eventstore.go
@@ -80,6 +80,10 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(AggregateType, GitHubIDPChangedEventType, GitHubIDPChangedEventMapper).
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPAddedEventType, GitHubEnterpriseIDPAddedEventMapper).
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPChangedEventType, GitHubEnterpriseIDPChangedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabIDPAddedEventType, GitLabIDPAddedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabIDPChangedEventType, GitLabIDPChangedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabSelfHostedIDPAddedEventType, GitLabSelfHostedIDPAddedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabSelfHostedIDPChangedEventType, GitLabSelfHostedIDPChangedEventMapper).
RegisterFilterEventMapper(AggregateType, GoogleIDPAddedEventType, GoogleIDPAddedEventMapper).
RegisterFilterEventMapper(AggregateType, GoogleIDPChangedEventType, GoogleIDPChangedEventMapper).
RegisterFilterEventMapper(AggregateType, LDAPIDPAddedEventType, LDAPIDPAddedEventMapper).
diff --git a/internal/repository/instance/idp.go b/internal/repository/instance/idp.go
index a7bec4ff6d..22aa4c41e3 100644
--- a/internal/repository/instance/idp.go
+++ b/internal/repository/instance/idp.go
@@ -20,6 +20,10 @@ const (
GitHubIDPChangedEventType eventstore.EventType = "instance.idp.github.changed"
GitHubEnterpriseIDPAddedEventType eventstore.EventType = "instance.idp.github_enterprise.added"
GitHubEnterpriseIDPChangedEventType eventstore.EventType = "instance.idp.github_enterprise.changed"
+ GitLabIDPAddedEventType eventstore.EventType = "instance.idp.gitlab.added"
+ GitLabIDPChangedEventType eventstore.EventType = "instance.idp.gitlab.changed"
+ GitLabSelfHostedIDPAddedEventType eventstore.EventType = "instance.idp.gitlab_self_hosted.added"
+ GitLabSelfHostedIDPChangedEventType eventstore.EventType = "instance.idp.gitlab_self_hosted.changed"
GoogleIDPAddedEventType eventstore.EventType = "instance.idp.google.added"
GoogleIDPChangedEventType eventstore.EventType = "instance.idp.google.changed"
LDAPIDPAddedEventType eventstore.EventType = "instance.idp.ldap.added"
@@ -425,6 +429,160 @@ func GitHubEnterpriseIDPChangedEventMapper(event *repository.Event) (eventstore.
return &GitHubEnterpriseIDPChangedEvent{GitHubEnterpriseIDPChangedEvent: *e.(*idp.GitHubEnterpriseIDPChangedEvent)}, nil
}
+type GitLabIDPAddedEvent struct {
+ idp.GitLabIDPAddedEvent
+}
+
+func NewGitLabIDPAddedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ clientID string,
+ clientSecret *crypto.CryptoValue,
+ scopes []string,
+ options idp.Options,
+) *GitLabIDPAddedEvent {
+
+ return &GitLabIDPAddedEvent{
+ GitLabIDPAddedEvent: *idp.NewGitLabIDPAddedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabIDPAddedEventType,
+ ),
+ id,
+ name,
+ clientID,
+ clientSecret,
+ scopes,
+ options,
+ ),
+ }
+}
+
+func GitLabIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabIDPAddedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabIDPAddedEvent{GitLabIDPAddedEvent: *e.(*idp.GitLabIDPAddedEvent)}, nil
+}
+
+type GitLabIDPChangedEvent struct {
+ idp.GitLabIDPChangedEvent
+}
+
+func NewGitLabIDPChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id string,
+ changes []idp.GitLabIDPChanges,
+) (*GitLabIDPChangedEvent, error) {
+
+ changedEvent, err := idp.NewGitLabIDPChangedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabIDPChangedEventType,
+ ),
+ id,
+ changes,
+ )
+ if err != nil {
+ return nil, err
+ }
+ return &GitLabIDPChangedEvent{GitLabIDPChangedEvent: *changedEvent}, nil
+}
+
+func GitLabIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabIDPChangedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabIDPChangedEvent{GitLabIDPChangedEvent: *e.(*idp.GitLabIDPChangedEvent)}, nil
+}
+
+type GitLabSelfHostedIDPAddedEvent struct {
+ idp.GitLabSelfHostedIDPAddedEvent
+}
+
+func NewGitLabSelfHostedIDPAddedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ issuer,
+ clientID string,
+ clientSecret *crypto.CryptoValue,
+ scopes []string,
+ options idp.Options,
+) *GitLabSelfHostedIDPAddedEvent {
+
+ return &GitLabSelfHostedIDPAddedEvent{
+ GitLabSelfHostedIDPAddedEvent: *idp.NewGitLabSelfHostedIDPAddedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabSelfHostedIDPAddedEventType,
+ ),
+ id,
+ name,
+ issuer,
+ clientID,
+ clientSecret,
+ scopes,
+ options,
+ ),
+ }
+}
+
+func GitLabSelfHostedIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabSelfHostedIDPAddedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabSelfHostedIDPAddedEvent{GitLabSelfHostedIDPAddedEvent: *e.(*idp.GitLabSelfHostedIDPAddedEvent)}, nil
+}
+
+type GitLabSelfHostedIDPChangedEvent struct {
+ idp.GitLabSelfHostedIDPChangedEvent
+}
+
+func NewGitLabSelfHostedIDPChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id string,
+ changes []idp.GitLabSelfHostedIDPChanges,
+) (*GitLabSelfHostedIDPChangedEvent, error) {
+
+ changedEvent, err := idp.NewGitLabSelfHostedIDPChangedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabSelfHostedIDPChangedEventType,
+ ),
+ id,
+ changes,
+ )
+ if err != nil {
+ return nil, err
+ }
+ return &GitLabSelfHostedIDPChangedEvent{GitLabSelfHostedIDPChangedEvent: *changedEvent}, nil
+}
+
+func GitLabSelfHostedIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabSelfHostedIDPChangedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabSelfHostedIDPChangedEvent{GitLabSelfHostedIDPChangedEvent: *e.(*idp.GitLabSelfHostedIDPChangedEvent)}, nil
+}
+
type GoogleIDPAddedEvent struct {
idp.GoogleIDPAddedEvent
}
diff --git a/internal/repository/org/eventstore.go b/internal/repository/org/eventstore.go
index bb288603ab..fc6128f7b1 100644
--- a/internal/repository/org/eventstore.go
+++ b/internal/repository/org/eventstore.go
@@ -88,6 +88,10 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(AggregateType, GitHubIDPChangedEventType, GitHubIDPChangedEventMapper).
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPAddedEventType, GitHubEnterpriseIDPAddedEventMapper).
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPChangedEventType, GitHubEnterpriseIDPChangedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabIDPAddedEventType, GitLabIDPAddedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabIDPChangedEventType, GitLabIDPChangedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabSelfHostedIDPAddedEventType, GitLabSelfHostedIDPAddedEventMapper).
+ RegisterFilterEventMapper(AggregateType, GitLabSelfHostedIDPChangedEventType, GitLabSelfHostedIDPChangedEventMapper).
RegisterFilterEventMapper(AggregateType, GoogleIDPAddedEventType, GoogleIDPAddedEventMapper).
RegisterFilterEventMapper(AggregateType, GoogleIDPChangedEventType, GoogleIDPChangedEventMapper).
RegisterFilterEventMapper(AggregateType, LDAPIDPAddedEventType, LDAPIDPAddedEventMapper).
diff --git a/internal/repository/org/idp.go b/internal/repository/org/idp.go
index b86c57610a..db9ad882f9 100644
--- a/internal/repository/org/idp.go
+++ b/internal/repository/org/idp.go
@@ -20,6 +20,10 @@ const (
GitHubIDPChangedEventType eventstore.EventType = "org.idp.github.changed"
GitHubEnterpriseIDPAddedEventType eventstore.EventType = "org.idp.github_enterprise.added"
GitHubEnterpriseIDPChangedEventType eventstore.EventType = "org.idp.github_enterprise.changed"
+ GitLabIDPAddedEventType eventstore.EventType = "org.idp.gitlab.added"
+ GitLabIDPChangedEventType eventstore.EventType = "org.idp.gitlab.changed"
+ GitLabSelfHostedIDPAddedEventType eventstore.EventType = "org.idp.gitlab_self_hosted.added"
+ GitLabSelfHostedIDPChangedEventType eventstore.EventType = "org.idp.gitlab_self_hosted.changed"
GoogleIDPAddedEventType eventstore.EventType = "org.idp.google.added"
GoogleIDPChangedEventType eventstore.EventType = "org.idp.google.changed"
LDAPIDPAddedEventType eventstore.EventType = "org.idp.ldap.added"
@@ -425,6 +429,160 @@ func GitHubEnterpriseIDPChangedEventMapper(event *repository.Event) (eventstore.
return &GitHubEnterpriseIDPChangedEvent{GitHubEnterpriseIDPChangedEvent: *e.(*idp.GitHubEnterpriseIDPChangedEvent)}, nil
}
+type GitLabIDPAddedEvent struct {
+ idp.GitLabIDPAddedEvent
+}
+
+func NewGitLabIDPAddedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ clientID string,
+ clientSecret *crypto.CryptoValue,
+ scopes []string,
+ options idp.Options,
+) *GitLabIDPAddedEvent {
+
+ return &GitLabIDPAddedEvent{
+ GitLabIDPAddedEvent: *idp.NewGitLabIDPAddedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabIDPAddedEventType,
+ ),
+ id,
+ name,
+ clientID,
+ clientSecret,
+ scopes,
+ options,
+ ),
+ }
+}
+
+func GitLabIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabIDPAddedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabIDPAddedEvent{GitLabIDPAddedEvent: *e.(*idp.GitLabIDPAddedEvent)}, nil
+}
+
+type GitLabIDPChangedEvent struct {
+ idp.GitLabIDPChangedEvent
+}
+
+func NewGitLabIDPChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id string,
+ changes []idp.GitLabIDPChanges,
+) (*GitLabIDPChangedEvent, error) {
+
+ changedEvent, err := idp.NewGitLabIDPChangedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabIDPChangedEventType,
+ ),
+ id,
+ changes,
+ )
+ if err != nil {
+ return nil, err
+ }
+ return &GitLabIDPChangedEvent{GitLabIDPChangedEvent: *changedEvent}, nil
+}
+
+func GitLabIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabIDPChangedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabIDPChangedEvent{GitLabIDPChangedEvent: *e.(*idp.GitLabIDPChangedEvent)}, nil
+}
+
+type GitLabSelfHostedIDPAddedEvent struct {
+ idp.GitLabSelfHostedIDPAddedEvent
+}
+
+func NewGitLabSelfHostedIDPAddedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id,
+ name,
+ issuer,
+ clientID string,
+ clientSecret *crypto.CryptoValue,
+ scopes []string,
+ options idp.Options,
+) *GitLabSelfHostedIDPAddedEvent {
+
+ return &GitLabSelfHostedIDPAddedEvent{
+ GitLabSelfHostedIDPAddedEvent: *idp.NewGitLabSelfHostedIDPAddedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabSelfHostedIDPAddedEventType,
+ ),
+ id,
+ name,
+ issuer,
+ clientID,
+ clientSecret,
+ scopes,
+ options,
+ ),
+ }
+}
+
+func GitLabSelfHostedIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabSelfHostedIDPAddedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabSelfHostedIDPAddedEvent{GitLabSelfHostedIDPAddedEvent: *e.(*idp.GitLabSelfHostedIDPAddedEvent)}, nil
+}
+
+type GitLabSelfHostedIDPChangedEvent struct {
+ idp.GitLabSelfHostedIDPChangedEvent
+}
+
+func NewGitLabSelfHostedIDPChangedEvent(
+ ctx context.Context,
+ aggregate *eventstore.Aggregate,
+ id string,
+ changes []idp.GitLabSelfHostedIDPChanges,
+) (*GitLabSelfHostedIDPChangedEvent, error) {
+
+ changedEvent, err := idp.NewGitLabSelfHostedIDPChangedEvent(
+ eventstore.NewBaseEventForPush(
+ ctx,
+ aggregate,
+ GitLabSelfHostedIDPChangedEventType,
+ ),
+ id,
+ changes,
+ )
+ if err != nil {
+ return nil, err
+ }
+ return &GitLabSelfHostedIDPChangedEvent{GitLabSelfHostedIDPChangedEvent: *changedEvent}, nil
+}
+
+func GitLabSelfHostedIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
+ e, err := idp.GitLabSelfHostedIDPChangedEventMapper(event)
+ if err != nil {
+ return nil, err
+ }
+
+ return &GitLabSelfHostedIDPChangedEvent{GitLabSelfHostedIDPChangedEvent: *e.(*idp.GitLabSelfHostedIDPChangedEvent)}, nil
+}
+
type GoogleIDPAddedEvent struct {
idp.GoogleIDPAddedEvent
}
diff --git a/proto/zitadel/admin.proto b/proto/zitadel/admin.proto
index 3325cc5e7a..f852cbe18d 100644
--- a/proto/zitadel/admin.proto
+++ b/proto/zitadel/admin.proto
@@ -1368,6 +1368,54 @@ service AdminService {
};
}
+ // Add a new GitLab identity provider on the instance
+ rpc AddGitLabProvider(AddGitLabProviderRequest) returns (AddGitLabProviderResponse) {
+ option (google.api.http) = {
+ post: "/idps/gitlab"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "iam.idp.write"
+ };
+ }
+
+ // Change an existing GitLab identity provider on the instance
+ rpc UpdateGitLabProvider(UpdateGitLabProviderRequest) returns (UpdateGitLabProviderResponse) {
+ option (google.api.http) = {
+ post: "/idps/gitlab/{id}"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "iam.idp.write"
+ };
+ }
+
+ // Add a new self hosted GitLab identity provider on the instance
+ rpc AddGitLabSelfHostedProvider(AddGitLabSelfHostedProviderRequest) returns (AddGitLabSelfHostedProviderResponse) {
+ option (google.api.http) = {
+ post: "/idps/gitlab_self_hosted"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "iam.idp.write"
+ };
+ }
+
+ // Change an existing self hosted GitLab identity provider on the instance
+ rpc UpdateGitLabSelfHostedProvider(UpdateGitLabSelfHostedProviderRequest) returns (UpdateGitLabSelfHostedProviderResponse) {
+ option (google.api.http) = {
+ post: "/idps/gitlab_self_hosted/{id}"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "iam.idp.write"
+ };
+ }
+
// Add a new Google identity provider on the instance
rpc AddGoogleProvider(AddGoogleProviderRequest) returns (AddGoogleProviderResponse) {
option (google.api.http) = {
@@ -4538,6 +4586,63 @@ message UpdateGitHubEnterpriseServerProviderResponse {
zitadel.v1.ObjectDetails details = 1;
}
+message AddGitLabProviderRequest {
+ // GitLab will be used as default, if no name is provided
+ string name = 1 [(validate.rules).string = {max_len: 200}];
+ string client_id = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_secret = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ repeated string scopes = 4 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 5;
+}
+
+message AddGitLabProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+ string id = 2;
+}
+
+message UpdateGitLabProviderRequest {
+ string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string name = 2 [(validate.rules).string = {max_len: 200}];
+ string client_id = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ // client_secret will only be updated if provided
+ string client_secret = 4 [(validate.rules).string = {max_len: 200}];
+ repeated string scopes = 5 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 6;
+}
+
+message UpdateGitLabProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+}
+
+message AddGitLabSelfHostedProviderRequest {
+ string issuer = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_id = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_secret = 4 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ repeated string scopes = 5 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 6;
+}
+
+message AddGitLabSelfHostedProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+ string id = 2;
+}
+
+message UpdateGitLabSelfHostedProviderRequest {
+ string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string issuer = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string name = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_id = 4 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ // client_secret will only be updated if provided
+ string client_secret = 5 [(validate.rules).string = {max_len: 200}];
+ repeated string scopes = 6 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 7;
+}
+
+message UpdateGitLabSelfHostedProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+}
+
message AddGoogleProviderRequest {
// Google will be used as default, if no name is provided
string name = 1 [(validate.rules).string = {max_len: 200}];
diff --git a/proto/zitadel/idp.proto b/proto/zitadel/idp.proto
index 1cda8d29ee..414d23347f 100644
--- a/proto/zitadel/idp.proto
+++ b/proto/zitadel/idp.proto
@@ -269,6 +269,8 @@ message ProviderConfig {
JWTConfig jwt = 6;
GitHubConfig github = 7;
GitHubEnterpriseServerConfig github_es = 8;
+ GitLabConfig gitlab = 9;
+ GitLabSelfHostedConfig gitlab_self_hosted = 10;
}
}
message OAuthConfig {
@@ -304,6 +306,17 @@ message GoogleConfig {
repeated string scopes = 2;
}
+message GitLabConfig {
+ string client_id = 1;
+ repeated string scopes = 2;
+}
+
+message GitLabSelfHostedConfig {
+ string issuer = 1;
+ string client_id = 2;
+ repeated string scopes = 3;
+}
+
message LDAPConfig {
string host = 1;
string port = 2;
diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto
index 5724270ce4..208c3584b0 100644
--- a/proto/zitadel/management.proto
+++ b/proto/zitadel/management.proto
@@ -6584,6 +6584,54 @@ service ManagementService {
};
}
+ // Add a new GitLab identity provider in the organization
+ rpc AddGitLabProvider(AddGitLabProviderRequest) returns (AddGitLabProviderResponse) {
+ option (google.api.http) = {
+ post: "/idps/gitlab"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "org.idp.write"
+ };
+ }
+
+ // Change an existing GitLab identity provider in the organization
+ rpc UpdateGitLabProvider(UpdateGitLabProviderRequest) returns (UpdateGitLabProviderResponse) {
+ option (google.api.http) = {
+ put: "/idps/gitlab/{id}"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "org.idp.write"
+ };
+ }
+
+ // Add a new self hosted GitLab identity provider in the organization
+ rpc AddGitLabSelfHostedProvider(AddGitLabSelfHostedProviderRequest) returns (AddGitLabSelfHostedProviderResponse) {
+ option (google.api.http) = {
+ post: "/idps/gitlab_self_hosted"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "org.idp.write"
+ };
+ }
+
+ // Change an existing self hosted GitLab identity provider in the organization
+ rpc UpdateGitLabSelfHostedProvider(UpdateGitLabSelfHostedProviderRequest) returns (UpdateGitLabSelfHostedProviderResponse) {
+ option (google.api.http) = {
+ put: "/idps/gitlab_self_hosted/{id}"
+ body: "*"
+ };
+
+ option (zitadel.v1.auth_option) = {
+ permission: "org.idp.write"
+ };
+ }
+
// Add a new Google identity provider in the organization
rpc AddGoogleProvider(AddGoogleProviderRequest) returns (AddGoogleProviderResponse) {
option (google.api.http) = {
@@ -11212,6 +11260,63 @@ message UpdateGitHubEnterpriseServerProviderResponse {
zitadel.v1.ObjectDetails details = 1;
}
+message AddGitLabProviderRequest {
+ // GitLab will be used as default, if no name is provided
+ string name = 1 [(validate.rules).string = {max_len: 200}];
+ string client_id = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_secret = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ repeated string scopes = 4 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 5;
+}
+
+message AddGitLabProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+ string id = 2;
+}
+
+message UpdateGitLabProviderRequest {
+ string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string name = 2 [(validate.rules).string = {max_len: 200}];
+ string client_id = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ // client_secret will only be updated if provided
+ string client_secret = 4 [(validate.rules).string = {max_len: 200}];
+ repeated string scopes = 5 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 6;
+}
+
+message UpdateGitLabProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+}
+
+message AddGitLabSelfHostedProviderRequest {
+ string issuer = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_id = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_secret = 4 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ repeated string scopes = 5 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 6;
+}
+
+message AddGitLabSelfHostedProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+ string id = 2;
+}
+
+message UpdateGitLabSelfHostedProviderRequest {
+ string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string issuer = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string name = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ string client_id = 4 [(validate.rules).string = {min_len: 1, max_len: 200}];
+ // client_secret will only be updated if provided
+ string client_secret = 5 [(validate.rules).string = {max_len: 200}];
+ repeated string scopes = 6 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
+ zitadel.idp.v1.Options provider_options = 7;
+}
+
+message UpdateGitLabSelfHostedProviderResponse {
+ zitadel.v1.ObjectDetails details = 1;
+}
+
message AddGoogleProviderRequest {
// Google will be used as default, if no name is provided
string name = 1 [(validate.rules).string = {max_len: 200}];