mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-01 00:47:23 +00:00
feat(api): add generic oauth provider template (#5260)
adds functionality to manage templates based OIDC IDPs
This commit is contained in:
parent
aa9518ac02
commit
737d14e81b
@ -86,7 +86,7 @@
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "6mb",
|
||||
"maximumError": "6mb"
|
||||
"maximumError": "7mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
|
2
docs/docs/apis/assets/assets.md
Normal file → Executable file
2
docs/docs/apis/assets/assets.md
Normal file → Executable file
@ -256,4 +256,4 @@ GET: /users/me/avatar
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -174,8 +174,29 @@ func (s *Server) ListProviders(ctx context.Context, req *admin_pb.ListProvidersR
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddGenericOAuthProvider(ctx context.Context, req *admin_pb.AddGenericOAuthProviderRequest) (*admin_pb.AddGenericOAuthProviderResponse, error) {
|
||||
id, details, err := s.command.AddInstanceGenericOAuthProvider(ctx, addGenericOAuthProviderToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.AddGenericOAuthProviderResponse{
|
||||
Id: id,
|
||||
Details: object_pb.DomainToAddDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateGenericOAuthProvider(ctx context.Context, req *admin_pb.UpdateGenericOAuthProviderRequest) (*admin_pb.UpdateGenericOAuthProviderResponse, error) {
|
||||
details, err := s.command.UpdateInstanceGenericOAuthProvider(ctx, req.Id, updateGenericOAuthProviderToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateGenericOAuthProviderResponse{
|
||||
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.AddOrgGoogleProvider(ctx, authz.GetCtxData(ctx).OrgID, addGoogleProviderToCommand(req))
|
||||
id, details, err := s.command.AddInstanceGoogleProvider(ctx, addGoogleProviderToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -186,7 +207,7 @@ func (s *Server) AddGoogleProvider(ctx context.Context, req *admin_pb.AddGoogleP
|
||||
}
|
||||
|
||||
func (s *Server) UpdateGoogleProvider(ctx context.Context, req *admin_pb.UpdateGoogleProviderRequest) (*admin_pb.UpdateGoogleProviderResponse, error) {
|
||||
details, err := s.command.UpdateOrgGoogleProvider(ctx, authz.GetCtxData(ctx).OrgID, req.Id, updateGoogleProviderToCommand(req))
|
||||
details, err := s.command.UpdateInstanceGoogleProvider(ctx, req.Id, updateGoogleProviderToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -201,6 +201,32 @@ func providerQueryToQuery(idpQuery *admin_pb.ProviderQuery) (query.SearchQuery,
|
||||
}
|
||||
}
|
||||
|
||||
func addGenericOAuthProviderToCommand(req *admin_pb.AddGenericOAuthProviderRequest) command.GenericOAuthProvider {
|
||||
return command.GenericOAuthProvider{
|
||||
Name: req.Name,
|
||||
ClientID: req.ClientId,
|
||||
ClientSecret: req.ClientSecret,
|
||||
AuthorizationEndpoint: req.AuthorizationEndpoint,
|
||||
TokenEndpoint: req.TokenEndpoint,
|
||||
UserEndpoint: req.UserEndpoint,
|
||||
Scopes: req.Scopes,
|
||||
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||
}
|
||||
}
|
||||
|
||||
func updateGenericOAuthProviderToCommand(req *admin_pb.UpdateGenericOAuthProviderRequest) command.GenericOAuthProvider {
|
||||
return command.GenericOAuthProvider{
|
||||
Name: req.Name,
|
||||
ClientID: req.ClientId,
|
||||
ClientSecret: req.ClientSecret,
|
||||
AuthorizationEndpoint: req.AuthorizationEndpoint,
|
||||
TokenEndpoint: req.TokenEndpoint,
|
||||
UserEndpoint: req.UserEndpoint,
|
||||
Scopes: req.Scopes,
|
||||
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||
}
|
||||
}
|
||||
|
||||
func addGoogleProviderToCommand(req *admin_pb.AddGoogleProviderRequest) command.GoogleProvider {
|
||||
return command.GoogleProvider{
|
||||
Name: req.Name,
|
||||
|
@ -402,31 +402,57 @@ func configToPb(config *query.IDPTemplate) *idp_pb.ProviderConfig {
|
||||
IsAutoUpdate: config.IsAutoUpdate,
|
||||
},
|
||||
}
|
||||
if config.OAuthIDPTemplate != nil {
|
||||
oauthConfigToPb(providerConfig, config.OAuthIDPTemplate)
|
||||
return providerConfig
|
||||
}
|
||||
if config.GoogleIDPTemplate != nil {
|
||||
providerConfig.Config = &idp_pb.ProviderConfig_Google{
|
||||
Google: &idp_pb.GoogleConfig{
|
||||
ClientId: config.GoogleIDPTemplate.ClientID,
|
||||
Scopes: config.GoogleIDPTemplate.Scopes,
|
||||
},
|
||||
}
|
||||
googleConfigToPb(providerConfig, config.GoogleIDPTemplate)
|
||||
return providerConfig
|
||||
}
|
||||
if config.LDAPIDPTemplate != nil {
|
||||
providerConfig.Config = &idp_pb.ProviderConfig_Ldap{
|
||||
Ldap: &idp_pb.LDAPConfig{
|
||||
Host: config.Host,
|
||||
Port: config.Port,
|
||||
Tls: config.TLS,
|
||||
BaseDn: config.BaseDN,
|
||||
UserObjectClass: config.UserObjectClass,
|
||||
UserUniqueAttribute: config.UserUniqueAttribute,
|
||||
Admin: config.Admin,
|
||||
Attributes: ldapAttributesToPb(config.LDAPAttributes),
|
||||
},
|
||||
}
|
||||
ldapConfigToPb(providerConfig, config.LDAPIDPTemplate)
|
||||
return providerConfig
|
||||
}
|
||||
return providerConfig
|
||||
}
|
||||
|
||||
func googleConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.GoogleIDPTemplate) {
|
||||
providerConfig.Config = &idp_pb.ProviderConfig_Google{
|
||||
Google: &idp_pb.GoogleConfig{
|
||||
ClientId: template.ClientID,
|
||||
Scopes: template.Scopes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func oauthConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.OAuthIDPTemplate) {
|
||||
providerConfig.Config = &idp_pb.ProviderConfig_Oauth{
|
||||
Oauth: &idp_pb.OAuthConfig{
|
||||
ClientId: template.ClientID,
|
||||
AuthorizationEndpoint: template.AuthorizationEndpoint,
|
||||
TokenEndpoint: template.TokenEndpoint,
|
||||
UserEndpoint: template.UserEndpoint,
|
||||
Scopes: template.Scopes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ldapConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.LDAPIDPTemplate) {
|
||||
providerConfig.Config = &idp_pb.ProviderConfig_Ldap{
|
||||
Ldap: &idp_pb.LDAPConfig{
|
||||
Host: template.Host,
|
||||
Port: template.Port,
|
||||
Tls: template.TLS,
|
||||
BaseDn: template.BaseDN,
|
||||
UserObjectClass: template.UserObjectClass,
|
||||
UserUniqueAttribute: template.UserUniqueAttribute,
|
||||
Admin: template.Admin,
|
||||
Attributes: ldapAttributesToPb(template.LDAPAttributes),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ldapAttributesToPb(attributes idp.LDAPAttributes) *idp_pb.LDAPAttributes {
|
||||
return &idp_pb.LDAPAttributes{
|
||||
IdAttribute: attributes.IDAttribute,
|
||||
|
@ -166,6 +166,27 @@ func (s *Server) ListProviders(ctx context.Context, req *mgmt_pb.ListProvidersRe
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddGenericOAuthProvider(ctx context.Context, req *mgmt_pb.AddGenericOAuthProviderRequest) (*mgmt_pb.AddGenericOAuthProviderResponse, error) {
|
||||
id, details, err := s.command.AddOrgGenericOAuthProvider(ctx, authz.GetCtxData(ctx).OrgID, addGenericOAuthProviderToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.AddGenericOAuthProviderResponse{
|
||||
Id: id,
|
||||
Details: object_pb.DomainToAddDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateGenericOAuthProvider(ctx context.Context, req *mgmt_pb.UpdateGenericOAuthProviderRequest) (*mgmt_pb.UpdateGenericOAuthProviderResponse, error) {
|
||||
details, err := s.command.UpdateOrgGenericOAuthProvider(ctx, authz.GetCtxData(ctx).OrgID, req.Id, updateGenericOAuthProviderToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.UpdateGenericOAuthProviderResponse{
|
||||
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 {
|
||||
|
@ -218,6 +218,32 @@ func providerQueryToQuery(idpQuery *mgmt_pb.ProviderQuery) (query.SearchQuery, e
|
||||
}
|
||||
}
|
||||
|
||||
func addGenericOAuthProviderToCommand(req *mgmt_pb.AddGenericOAuthProviderRequest) command.GenericOAuthProvider {
|
||||
return command.GenericOAuthProvider{
|
||||
Name: req.Name,
|
||||
ClientID: req.ClientId,
|
||||
ClientSecret: req.ClientSecret,
|
||||
AuthorizationEndpoint: req.AuthorizationEndpoint,
|
||||
TokenEndpoint: req.TokenEndpoint,
|
||||
UserEndpoint: req.UserEndpoint,
|
||||
Scopes: req.Scopes,
|
||||
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||
}
|
||||
}
|
||||
|
||||
func updateGenericOAuthProviderToCommand(req *mgmt_pb.UpdateGenericOAuthProviderRequest) command.GenericOAuthProvider {
|
||||
return command.GenericOAuthProvider{
|
||||
Name: req.Name,
|
||||
ClientID: req.ClientId,
|
||||
ClientSecret: req.ClientSecret,
|
||||
AuthorizationEndpoint: req.AuthorizationEndpoint,
|
||||
TokenEndpoint: req.TokenEndpoint,
|
||||
UserEndpoint: req.UserEndpoint,
|
||||
Scopes: req.Scopes,
|
||||
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||
}
|
||||
}
|
||||
|
||||
func addGoogleProviderToCommand(req *mgmt_pb.AddGoogleProviderRequest) command.GoogleProvider {
|
||||
return command.GoogleProvider{
|
||||
Name: req.Name,
|
||||
|
@ -2,6 +2,17 @@ package command
|
||||
|
||||
import "github.com/zitadel/zitadel/internal/repository/idp"
|
||||
|
||||
type GenericOAuthProvider struct {
|
||||
Name string
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
AuthorizationEndpoint string
|
||||
TokenEndpoint string
|
||||
UserEndpoint string
|
||||
Scopes []string
|
||||
IDPOptions idp.Options
|
||||
}
|
||||
|
||||
type GoogleProvider struct {
|
||||
Name string
|
||||
ClientID string
|
||||
|
@ -10,6 +10,118 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/idpconfig"
|
||||
)
|
||||
|
||||
type OAuthIDPWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Name string
|
||||
ID string
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
AuthorizationEndpoint string
|
||||
TokenEndpoint string
|
||||
UserEndpoint string
|
||||
Scopes []string
|
||||
idp.Options
|
||||
|
||||
State domain.IDPState
|
||||
}
|
||||
|
||||
func (wm *OAuthIDPWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *idp.OAuthIDPAddedEvent:
|
||||
wm.reduceAddedEvent(e)
|
||||
case *idp.OAuthIDPChangedEvent:
|
||||
wm.reduceChangedEvent(e)
|
||||
case *idp.RemovedEvent:
|
||||
wm.State = domain.IDPStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OAuthIDPWriteModel) reduceAddedEvent(e *idp.OAuthIDPAddedEvent) {
|
||||
wm.Name = e.Name
|
||||
wm.ClientID = e.ClientID
|
||||
wm.ClientSecret = e.ClientSecret
|
||||
wm.AuthorizationEndpoint = e.AuthorizationEndpoint
|
||||
wm.TokenEndpoint = e.TokenEndpoint
|
||||
wm.UserEndpoint = e.UserEndpoint
|
||||
wm.Scopes = e.Scopes
|
||||
wm.State = domain.IDPStateActive
|
||||
}
|
||||
|
||||
func (wm *OAuthIDPWriteModel) reduceChangedEvent(e *idp.OAuthIDPChangedEvent) {
|
||||
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.AuthorizationEndpoint != nil {
|
||||
wm.AuthorizationEndpoint = *e.AuthorizationEndpoint
|
||||
}
|
||||
if e.TokenEndpoint != nil {
|
||||
wm.TokenEndpoint = *e.TokenEndpoint
|
||||
}
|
||||
if e.UserEndpoint != nil {
|
||||
wm.UserEndpoint = *e.UserEndpoint
|
||||
}
|
||||
if e.Scopes != nil {
|
||||
wm.Scopes = e.Scopes
|
||||
}
|
||||
wm.Options.ReduceChanges(e.OptionChanges)
|
||||
}
|
||||
|
||||
func (wm *OAuthIDPWriteModel) NewChanges(
|
||||
name,
|
||||
clientID,
|
||||
clientSecretString string,
|
||||
secretCrypto crypto.Crypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) ([]idp.OAuthIDPChanges, error) {
|
||||
changes := make([]idp.OAuthIDPChanges, 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.ChangeOAuthClientSecret(clientSecret))
|
||||
}
|
||||
if wm.ClientID != clientID {
|
||||
changes = append(changes, idp.ChangeOAuthClientID(clientID))
|
||||
}
|
||||
if wm.Name != name {
|
||||
changes = append(changes, idp.ChangeOAuthName(name))
|
||||
}
|
||||
if wm.AuthorizationEndpoint != authorizationEndpoint {
|
||||
changes = append(changes, idp.ChangeOAuthAuthorizationEndpoint(authorizationEndpoint))
|
||||
}
|
||||
if wm.TokenEndpoint != tokenEndpoint {
|
||||
changes = append(changes, idp.ChangeOAuthTokenEndpoint(tokenEndpoint))
|
||||
}
|
||||
if wm.UserEndpoint != userEndpoint {
|
||||
changes = append(changes, idp.ChangeOAuthUserEndpoint(userEndpoint))
|
||||
}
|
||||
if !reflect.DeepEqual(wm.Scopes, scopes) {
|
||||
changes = append(changes, idp.ChangeOAuthScopes(scopes))
|
||||
}
|
||||
opts := wm.Options.Changes(options)
|
||||
if !opts.IsZero() {
|
||||
changes = append(changes, idp.ChangeOAuthOptions(opts))
|
||||
}
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
type GoogleIDPWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
@ -259,6 +371,10 @@ type IDPRemoveWriteModel struct {
|
||||
func (wm *IDPRemoveWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *idp.OAuthIDPAddedEvent:
|
||||
wm.reduceAdded(e.ID, e.Name)
|
||||
case *idp.OAuthIDPChangedEvent:
|
||||
wm.reduceChanged(e.ID, e.Name)
|
||||
case *idp.GoogleIDPAddedEvent:
|
||||
wm.reduceAdded(e.ID, e.Name)
|
||||
case *idp.GoogleIDPChangedEvent:
|
||||
|
@ -13,13 +13,57 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
)
|
||||
|
||||
func (c *Commands) AddInstanceGoogleProvider(ctx context.Context, provider GoogleProvider) (string, *domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
func (c *Commands) AddInstanceGenericOAuthProvider(ctx context.Context, provider GenericOAuthProvider) (string, *domain.ObjectDetails, error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
id, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceGoogleProvider(instanceAgg, id, provider))
|
||||
writeModel := NewOAuthInstanceIDPWriteModel(instanceID, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceOAuthProvider(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) UpdateInstanceGenericOAuthProvider(ctx context.Context, id string, provider GenericOAuthProvider) (*domain.ObjectDetails, error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
writeModel := NewOAuthInstanceIDPWriteModel(instanceID, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceOAuthProvider(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)
|
||||
id, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
writeModel := NewGoogleInstanceIDPWriteModel(instanceID, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceGoogleProvider(instanceAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -31,14 +75,20 @@ func (c *Commands) AddInstanceGoogleProvider(ctx context.Context, provider Googl
|
||||
}
|
||||
|
||||
func (c *Commands) UpdateInstanceGoogleProvider(ctx context.Context, id string, provider GoogleProvider) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceGoogleProvider(instanceAgg, id, provider))
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
writeModel := NewGoogleInstanceIDPWriteModel(instanceID, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceGoogleProvider(instanceAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cmds) == 0 {
|
||||
// no change, so return directly
|
||||
return &domain.ObjectDetails{}, nil
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: writeModel.ProcessedSequence,
|
||||
EventDate: writeModel.ChangeDate,
|
||||
ResourceOwner: writeModel.ResourceOwner,
|
||||
}, nil
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
@ -48,12 +98,14 @@ func (c *Commands) UpdateInstanceGoogleProvider(ctx context.Context, id string,
|
||||
}
|
||||
|
||||
func (c *Commands) AddInstanceLDAPProvider(ctx context.Context, provider LDAPProvider) (string, *domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
id, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceLDAPProvider(instanceAgg, id, provider))
|
||||
writeModel := NewLDAPInstanceIDPWriteModel(instanceID, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceLDAPProvider(instanceAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -65,14 +117,20 @@ func (c *Commands) AddInstanceLDAPProvider(ctx context.Context, provider LDAPPro
|
||||
}
|
||||
|
||||
func (c *Commands) UpdateInstanceLDAPProvider(ctx context.Context, id string, provider LDAPProvider) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceLDAPProvider(instanceAgg, id, provider))
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
writeModel := NewLDAPInstanceIDPWriteModel(instanceID, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceLDAPProvider(instanceAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cmds) == 0 {
|
||||
// no change, so return directly
|
||||
return &domain.ObjectDetails{}, nil
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: writeModel.ProcessedSequence,
|
||||
EventDate: writeModel.ChangeDate,
|
||||
ResourceOwner: writeModel.ResourceOwner,
|
||||
}, nil
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
@ -94,7 +152,113 @@ func (c *Commands) DeleteInstanceProvider(ctx context.Context, id string) (*doma
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddInstanceGoogleProvider(a *instance.Aggregate, id string, provider GoogleProvider) preparation.Validation {
|
||||
func (c *Commands) prepareAddInstanceOAuthProvider(a *instance.Aggregate, writeModel *InstanceOAuthIDPWriteModel, provider GenericOAuthProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D32ef", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Dbgzf", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-DF4ga", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.AuthorizationEndpoint = strings.TrimSpace(provider.AuthorizationEndpoint); provider.AuthorizationEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-B23bs", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.TokenEndpoint = strings.TrimSpace(provider.TokenEndpoint); provider.TokenEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D2gj8", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Fb8jk", "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.NewOAuthIDPAddedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
secret,
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
provider.Scopes,
|
||||
provider.IDPOptions,
|
||||
),
|
||||
}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateInstanceOAuthProvider(a *instance.Aggregate, writeModel *InstanceOAuthIDPWriteModel, provider GenericOAuthProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D32ef", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Dbgzf", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.AuthorizationEndpoint = strings.TrimSpace(provider.AuthorizationEndpoint); provider.AuthorizationEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-B23bs", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.TokenEndpoint = strings.TrimSpace(provider.TokenEndpoint); provider.TokenEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D2gj8", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Fb8jk", "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-D3r1s", "Errors.Instance.IDPConfig.NotExisting")
|
||||
}
|
||||
event, err := writeModel.NewChangedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
provider.ClientSecret,
|
||||
c.idpConfigEncryption,
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
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) prepareAddInstanceGoogleProvider(a *instance.Aggregate, writeModel *InstanceGoogleIDPWriteModel, provider GoogleProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-D3fvs", "Errors.Invalid.Argument")
|
||||
@ -103,7 +267,6 @@ func (c *Commands) prepareAddInstanceGoogleProvider(a *instance.Aggregate, id st
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-W2vqs", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewGoogleInstanceIDPWriteModel(a.InstanceID, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -120,7 +283,7 @@ func (c *Commands) prepareAddInstanceGoogleProvider(a *instance.Aggregate, id st
|
||||
instance.NewGoogleIDPAddedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
secret,
|
||||
@ -132,16 +295,15 @@ func (c *Commands) prepareAddInstanceGoogleProvider(a *instance.Aggregate, id st
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateInstanceGoogleProvider(a *instance.Aggregate, id string, provider GoogleProvider) preparation.Validation {
|
||||
func (c *Commands) prepareUpdateInstanceGoogleProvider(a *instance.Aggregate, writeModel *InstanceGoogleIDPWriteModel, provider GoogleProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if id = strings.TrimSpace(id); id == "" {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-S32t1", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-ds432", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewGoogleInstanceIDPWriteModel(a.InstanceID, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -156,7 +318,7 @@ func (c *Commands) prepareUpdateInstanceGoogleProvider(a *instance.Aggregate, id
|
||||
event, err := writeModel.NewChangedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
provider.ClientSecret,
|
||||
@ -175,7 +337,7 @@ func (c *Commands) prepareUpdateInstanceGoogleProvider(a *instance.Aggregate, id
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddInstanceLDAPProvider(a *instance.Aggregate, id string, provider LDAPProvider) preparation.Validation {
|
||||
func (c *Commands) prepareAddInstanceLDAPProvider(a *instance.Aggregate, writeModel *InstanceLDAPIDPWriteModel, provider LDAPProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SAfdd", "Errors.Invalid.Argument")
|
||||
@ -199,7 +361,6 @@ func (c *Commands) prepareAddInstanceLDAPProvider(a *instance.Aggregate, id stri
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-sdf5h", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewLDAPInstanceIDPWriteModel(a.InstanceID, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -216,7 +377,7 @@ func (c *Commands) prepareAddInstanceLDAPProvider(a *instance.Aggregate, id stri
|
||||
instance.NewLDAPIDPAddedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.Host,
|
||||
provider.Port,
|
||||
@ -234,9 +395,9 @@ func (c *Commands) prepareAddInstanceLDAPProvider(a *instance.Aggregate, id stri
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateInstanceLDAPProvider(a *instance.Aggregate, id string, provider LDAPProvider) preparation.Validation {
|
||||
func (c *Commands) prepareUpdateInstanceLDAPProvider(a *instance.Aggregate, writeModel *InstanceLDAPIDPWriteModel, provider LDAPProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if id = strings.TrimSpace(id); id == "" {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Dgdbs", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
@ -258,7 +419,6 @@ func (c *Commands) prepareUpdateInstanceLDAPProvider(a *instance.Aggregate, id s
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-DG45z", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewLDAPInstanceIDPWriteModel(a.InstanceID, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -273,7 +433,7 @@ func (c *Commands) prepareUpdateInstanceLDAPProvider(a *instance.Aggregate, id s
|
||||
event, err := writeModel.NewChangedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
writeModel.ID,
|
||||
writeModel.Name,
|
||||
provider.Name,
|
||||
provider.Host,
|
||||
|
@ -9,6 +9,89 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
)
|
||||
|
||||
type InstanceOAuthIDPWriteModel struct {
|
||||
OAuthIDPWriteModel
|
||||
}
|
||||
|
||||
func NewOAuthInstanceIDPWriteModel(instanceID, id string) *InstanceOAuthIDPWriteModel {
|
||||
return &InstanceOAuthIDPWriteModel{
|
||||
OAuthIDPWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: instanceID,
|
||||
ResourceOwner: instanceID,
|
||||
},
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *InstanceOAuthIDPWriteModel) Reduce() error {
|
||||
return wm.OAuthIDPWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *InstanceOAuthIDPWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *instance.OAuthIDPAddedEvent:
|
||||
wm.OAuthIDPWriteModel.AppendEvents(&e.OAuthIDPAddedEvent)
|
||||
case *instance.OAuthIDPChangedEvent:
|
||||
wm.OAuthIDPWriteModel.AppendEvents(&e.OAuthIDPChangedEvent)
|
||||
case *instance.IDPRemovedEvent:
|
||||
wm.OAuthIDPWriteModel.AppendEvents(&e.RemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *InstanceOAuthIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(instance.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
instance.OAuthIDPAddedEventType,
|
||||
instance.OAuthIDPChangedEventType,
|
||||
instance.IDPRemovedEventType,
|
||||
).
|
||||
EventData(map[string]interface{}{"id": wm.ID}).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *InstanceOAuthIDPWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id,
|
||||
name,
|
||||
clientID,
|
||||
clientSecretString string,
|
||||
secretCrypto crypto.Crypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) (*instance.OAuthIDPChangedEvent, error) {
|
||||
|
||||
changes, err := wm.OAuthIDPWriteModel.NewChanges(
|
||||
name,
|
||||
clientID,
|
||||
clientSecretString,
|
||||
secretCrypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint,
|
||||
scopes,
|
||||
options,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return instance.NewOAuthIDPChangedEvent(ctx, aggregate, id, changes)
|
||||
}
|
||||
|
||||
type InstanceGoogleIDPWriteModel struct {
|
||||
GoogleIDPWriteModel
|
||||
}
|
||||
@ -76,11 +159,7 @@ func (wm *InstanceGoogleIDPWriteModel) NewChangedEvent(
|
||||
if len(changes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
changeEvent, err := instance.NewGoogleIDPChangedEvent(ctx, aggregate, id, changes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return changeEvent, nil
|
||||
return instance.NewGoogleIDPChangedEvent(ctx, aggregate, id, changes)
|
||||
}
|
||||
|
||||
type InstanceLDAPIDPWriteModel struct {
|
||||
@ -107,19 +186,10 @@ func (wm *InstanceLDAPIDPWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *instance.LDAPIDPAddedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.LDAPIDPWriteModel.AppendEvents(&e.LDAPIDPAddedEvent)
|
||||
case *instance.LDAPIDPChangedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.LDAPIDPWriteModel.AppendEvents(&e.LDAPIDPChangedEvent)
|
||||
case *instance.IDPRemovedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.LDAPIDPWriteModel.AppendEvents(&e.RemovedEvent)
|
||||
default:
|
||||
wm.LDAPIDPWriteModel.AppendEvents(e)
|
||||
@ -138,6 +208,7 @@ func (wm *InstanceLDAPIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
instance.LDAPIDPChangedEventType,
|
||||
instance.IDPRemovedEventType,
|
||||
).
|
||||
EventData(map[string]interface{}{"id": wm.ID}).
|
||||
Builder()
|
||||
}
|
||||
|
||||
@ -180,11 +251,7 @@ func (wm *InstanceLDAPIDPWriteModel) NewChangedEvent(
|
||||
if len(changes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
changeEvent, err := instance.NewLDAPIDPChangedEvent(ctx, aggregate, id, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return changeEvent, nil
|
||||
return instance.NewLDAPIDPChangedEvent(ctx, aggregate, id, oldName, changes)
|
||||
}
|
||||
|
||||
type InstanceIDPRemoveWriteModel struct {
|
||||
@ -210,6 +277,10 @@ func (wm *InstanceIDPRemoveWriteModel) Reduce() error {
|
||||
func (wm *InstanceIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *instance.OAuthIDPAddedEvent:
|
||||
wm.IDPRemoveWriteModel.AppendEvents(&e.OAuthIDPAddedEvent)
|
||||
case *instance.OAuthIDPChangedEvent:
|
||||
wm.IDPRemoveWriteModel.AppendEvents(&e.OAuthIDPChangedEvent)
|
||||
case *instance.GoogleIDPAddedEvent:
|
||||
wm.IDPRemoveWriteModel.AppendEvents(&e.GoogleIDPAddedEvent)
|
||||
case *instance.GoogleIDPChangedEvent:
|
||||
@ -233,11 +304,14 @@ func (wm *InstanceIDPRemoveWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
AggregateTypes(instance.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
instance.OAuthIDPAddedEventType,
|
||||
instance.OAuthIDPChangedEventType,
|
||||
instance.GoogleIDPAddedEventType,
|
||||
instance.GoogleIDPChangedEventType,
|
||||
instance.LDAPIDPAddedEventType,
|
||||
instance.LDAPIDPChangedEventType,
|
||||
instance.IDPRemovedEventType,
|
||||
).
|
||||
EventData(map[string]interface{}{"id": wm.ID}).
|
||||
Builder()
|
||||
}
|
||||
|
@ -20,6 +20,542 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
provider GenericOAuthProvider
|
||||
}
|
||||
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: GenericOAuthProvider{},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid clientID",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid clientSecret",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid auth endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid token endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid user endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"instance1",
|
||||
instance.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
},
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
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.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
[]string{"user"},
|
||||
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: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
Scopes: []string{"user"},
|
||||
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.AddInstanceGenericOAuthProvider(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_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
id string
|
||||
provider GenericOAuthProvider
|
||||
}
|
||||
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: GenericOAuthProvider{},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid name",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid clientID",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid auth endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid token endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid user endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errors.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"instance1",
|
||||
func() eventstore.Command {
|
||||
t := true
|
||||
event, _ := instance.NewOAuthIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
[]idp.OAuthIDPChanges{
|
||||
idp.ChangeOAuthName("new name"),
|
||||
idp.ChangeOAuthClientID("clientID2"),
|
||||
idp.ChangeOAuthClientSecret(&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("newSecret"),
|
||||
}),
|
||||
idp.ChangeOAuthAuthorizationEndpoint("new auth"),
|
||||
idp.ChangeOAuthTokenEndpoint("new token"),
|
||||
idp.ChangeOAuthUserEndpoint("new user"),
|
||||
idp.ChangeOAuthScopes([]string{"openid", "profile"}),
|
||||
idp.ChangeOAuthOptions(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: GenericOAuthProvider{
|
||||
Name: "new name",
|
||||
ClientID: "clientID2",
|
||||
ClientSecret: "newSecret",
|
||||
AuthorizationEndpoint: "new auth",
|
||||
TokenEndpoint: "new token",
|
||||
UserEndpoint: "new user",
|
||||
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.UpdateInstanceGenericOAuthProvider(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
|
||||
@ -281,7 +817,7 @@ func TestCommandSide_UpdateInstanceGoogleIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{},
|
||||
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -893,7 +1429,7 @@ func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{},
|
||||
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -12,13 +12,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
)
|
||||
|
||||
func (c *Commands) AddOrgGenericOAuthProvider(ctx context.Context, resourceOwner string, provider GenericOAuthProvider) (string, *domain.ObjectDetails, error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
id, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
writeModel := NewOAuthOrgIDPWriteModel(resourceOwner, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgOAuthProvider(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) UpdateOrgGenericOAuthProvider(ctx context.Context, resourceOwner, id string, provider GenericOAuthProvider) (*domain.ObjectDetails, error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
writeModel := NewOAuthOrgIDPWriteModel(resourceOwner, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgOAuthProvider(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()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgGoogleProvider(orgAgg, resourceOwner, id, provider))
|
||||
writeModel := NewGoogleOrgIDPWriteModel(resourceOwner, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgGoogleProvider(orgAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -31,13 +72,18 @@ func (c *Commands) AddOrgGoogleProvider(ctx context.Context, resourceOwner strin
|
||||
|
||||
func (c *Commands) UpdateOrgGoogleProvider(ctx context.Context, resourceOwner, id string, provider GoogleProvider) (*domain.ObjectDetails, error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgGoogleProvider(orgAgg, resourceOwner, id, provider))
|
||||
writeModel := NewGoogleOrgIDPWriteModel(resourceOwner, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgGoogleProvider(orgAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cmds) == 0 {
|
||||
// no change, so return directly
|
||||
return &domain.ObjectDetails{}, nil
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: writeModel.ProcessedSequence,
|
||||
EventDate: writeModel.ChangeDate,
|
||||
ResourceOwner: writeModel.ResourceOwner,
|
||||
}, nil
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
@ -52,7 +98,8 @@ func (c *Commands) AddOrgLDAPProvider(ctx context.Context, resourceOwner string,
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgLDAPProvider(orgAgg, resourceOwner, id, provider))
|
||||
writeModel := NewLDAPOrgIDPWriteModel(resourceOwner, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgLDAPProvider(orgAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -65,13 +112,18 @@ func (c *Commands) AddOrgLDAPProvider(ctx context.Context, resourceOwner string,
|
||||
|
||||
func (c *Commands) UpdateOrgLDAPProvider(ctx context.Context, resourceOwner, id string, provider LDAPProvider) (*domain.ObjectDetails, error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgLDAPProvider(orgAgg, resourceOwner, id, provider))
|
||||
writeModel := NewLDAPOrgIDPWriteModel(resourceOwner, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgLDAPProvider(orgAgg, writeModel, provider))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cmds) == 0 {
|
||||
// no change, so return directly
|
||||
return &domain.ObjectDetails{}, nil
|
||||
return &domain.ObjectDetails{
|
||||
Sequence: writeModel.ProcessedSequence,
|
||||
EventDate: writeModel.ChangeDate,
|
||||
ResourceOwner: writeModel.ResourceOwner,
|
||||
}, nil
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
@ -93,16 +145,27 @@ func (c *Commands) DeleteOrgProvider(ctx context.Context, resourceOwner, id stri
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddOrgGoogleProvider(a *org.Aggregate, resourceOwner, id string, provider GoogleProvider) preparation.Validation {
|
||||
func (c *Commands) prepareAddOrgOAuthProvider(a *org.Aggregate, writeModel *OrgOAuthIDPWriteModel, provider GenericOAuthProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-D32ef", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-D3fvs", "Errors.Invalid.Argument")
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Dbgzf", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-W2vqs", "Errors.Invalid.Argument")
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-DF4ga", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.AuthorizationEndpoint = strings.TrimSpace(provider.AuthorizationEndpoint); provider.AuthorizationEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-B23bs", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.TokenEndpoint = strings.TrimSpace(provider.TokenEndpoint); provider.TokenEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-D2gj8", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Fb8jk", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewGoogleOrgIDPWriteModel(resourceOwner, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -116,22 +179,127 @@ func (c *Commands) prepareAddOrgGoogleProvider(a *org.Aggregate, resourceOwner,
|
||||
return nil, err
|
||||
}
|
||||
return []eventstore.Command{
|
||||
org.NewGoogleIDPAddedEvent(ctx, &a.Aggregate, id, provider.Name, provider.ClientID, secret, provider.Scopes, provider.IDPOptions),
|
||||
org.NewOAuthIDPAddedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
secret,
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
provider.Scopes,
|
||||
provider.IDPOptions,
|
||||
),
|
||||
}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateOrgGoogleProvider(a *org.Aggregate, resourceOwner, id string, provider GoogleProvider) preparation.Validation {
|
||||
func (c *Commands) prepareUpdateOrgOAuthProvider(a *org.Aggregate, writeModel *OrgOAuthIDPWriteModel, provider GenericOAuthProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if id = strings.TrimSpace(id); id == "" {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-asfsa", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-D32ef", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Dbgzf", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.AuthorizationEndpoint = strings.TrimSpace(provider.AuthorizationEndpoint); provider.AuthorizationEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-B23bs", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.TokenEndpoint = strings.TrimSpace(provider.TokenEndpoint); provider.TokenEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-D2gj8", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Fb8jk", "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-JNsd3", "Errors.Org.IDPConfig.NotExisting")
|
||||
}
|
||||
event, err := writeModel.NewChangedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
provider.ClientSecret,
|
||||
c.idpConfigEncryption,
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
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 == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-D3fvs", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-W2vqs", "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.NewGoogleIDPAddedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
secret,
|
||||
provider.Scopes,
|
||||
provider.IDPOptions,
|
||||
),
|
||||
}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateOrgGoogleProvider(a *org.Aggregate, writeModel *OrgGoogleIDPWriteModel, provider GoogleProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-S32t1", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-ds432", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewGoogleOrgIDPWriteModel(resourceOwner, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -146,7 +314,7 @@ func (c *Commands) prepareUpdateOrgGoogleProvider(a *org.Aggregate, resourceOwne
|
||||
event, err := writeModel.NewChangedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.ClientID,
|
||||
provider.ClientSecret,
|
||||
@ -165,7 +333,7 @@ func (c *Commands) prepareUpdateOrgGoogleProvider(a *org.Aggregate, resourceOwne
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddOrgLDAPProvider(a *org.Aggregate, resourceOwner, id string, provider LDAPProvider) preparation.Validation {
|
||||
func (c *Commands) prepareAddOrgLDAPProvider(a *org.Aggregate, writeModel *OrgLDAPIDPWriteModel, provider LDAPProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-SAfdd", "Errors.Invalid.Argument")
|
||||
@ -189,7 +357,6 @@ func (c *Commands) prepareAddOrgLDAPProvider(a *org.Aggregate, resourceOwner, id
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-sdf5h", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewLDAPOrgIDPWriteModel(resourceOwner, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -206,7 +373,7 @@ func (c *Commands) prepareAddOrgLDAPProvider(a *org.Aggregate, resourceOwner, id
|
||||
org.NewLDAPIDPAddedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
writeModel.ID,
|
||||
provider.Name,
|
||||
provider.Host,
|
||||
provider.Port,
|
||||
@ -224,9 +391,9 @@ func (c *Commands) prepareAddOrgLDAPProvider(a *org.Aggregate, resourceOwner, id
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateOrgLDAPProvider(a *org.Aggregate, resourceOwner, id string, provider LDAPProvider) preparation.Validation {
|
||||
func (c *Commands) prepareUpdateOrgLDAPProvider(a *org.Aggregate, writeModel *OrgLDAPIDPWriteModel, provider LDAPProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if id = strings.TrimSpace(id); id == "" {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Dgdbs", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
@ -248,7 +415,6 @@ func (c *Commands) prepareUpdateOrgLDAPProvider(a *org.Aggregate, resourceOwner,
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-DG45z", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
writeModel := NewLDAPOrgIDPWriteModel(resourceOwner, id)
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -263,7 +429,7 @@ func (c *Commands) prepareUpdateOrgLDAPProvider(a *org.Aggregate, resourceOwner,
|
||||
event, err := writeModel.NewChangedEvent(
|
||||
ctx,
|
||||
&a.Aggregate,
|
||||
id,
|
||||
writeModel.ID,
|
||||
writeModel.Name,
|
||||
provider.Name,
|
||||
provider.Host,
|
||||
|
@ -9,6 +9,91 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
)
|
||||
|
||||
type OrgOAuthIDPWriteModel struct {
|
||||
OAuthIDPWriteModel
|
||||
}
|
||||
|
||||
func NewOAuthOrgIDPWriteModel(orgID, id string) *OrgOAuthIDPWriteModel {
|
||||
return &OrgOAuthIDPWriteModel{
|
||||
OAuthIDPWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
ID: id,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgOAuthIDPWriteModel) Reduce() error {
|
||||
return wm.OAuthIDPWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgOAuthIDPWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.OAuthIDPAddedEvent:
|
||||
wm.OAuthIDPWriteModel.AppendEvents(&e.OAuthIDPAddedEvent)
|
||||
case *org.OAuthIDPChangedEvent:
|
||||
wm.OAuthIDPWriteModel.AppendEvents(&e.OAuthIDPChangedEvent)
|
||||
case *org.IDPRemovedEvent:
|
||||
wm.OAuthIDPWriteModel.AppendEvents(&e.RemovedEvent)
|
||||
default:
|
||||
wm.OAuthIDPWriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgOAuthIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
org.OAuthIDPAddedEventType,
|
||||
org.OAuthIDPChangedEventType,
|
||||
org.IDPRemovedEventType,
|
||||
).
|
||||
EventData(map[string]interface{}{"id": wm.ID}).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *OrgOAuthIDPWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id,
|
||||
name,
|
||||
clientID,
|
||||
clientSecretString string,
|
||||
secretCrypto crypto.Crypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) (*org.OAuthIDPChangedEvent, error) {
|
||||
|
||||
changes, err := wm.OAuthIDPWriteModel.NewChanges(
|
||||
name,
|
||||
clientID,
|
||||
clientSecretString,
|
||||
secretCrypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint,
|
||||
scopes,
|
||||
options,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return org.NewOAuthIDPChangedEvent(ctx, aggregate, id, changes)
|
||||
}
|
||||
|
||||
type OrgGoogleIDPWriteModel struct {
|
||||
GoogleIDPWriteModel
|
||||
}
|
||||
@ -78,11 +163,7 @@ func (wm *OrgGoogleIDPWriteModel) NewChangedEvent(
|
||||
if len(changes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
changeEvent, err := org.NewGoogleIDPChangedEvent(ctx, aggregate, id, changes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return changeEvent, nil
|
||||
return org.NewGoogleIDPChangedEvent(ctx, aggregate, id, changes)
|
||||
}
|
||||
|
||||
type OrgLDAPIDPWriteModel struct {
|
||||
@ -109,19 +190,10 @@ func (wm *OrgLDAPIDPWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.LDAPIDPAddedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.LDAPIDPWriteModel.AppendEvents(&e.LDAPIDPAddedEvent)
|
||||
case *org.LDAPIDPChangedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.LDAPIDPWriteModel.AppendEvents(&e.LDAPIDPChangedEvent)
|
||||
case *org.IDPRemovedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.LDAPIDPWriteModel.AppendEvents(&e.RemovedEvent)
|
||||
default:
|
||||
wm.LDAPIDPWriteModel.AppendEvents(e)
|
||||
@ -140,6 +212,7 @@ func (wm *OrgLDAPIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
org.LDAPIDPChangedEventType,
|
||||
org.IDPRemovedEventType,
|
||||
).
|
||||
EventData(map[string]interface{}{"id": wm.ID}).
|
||||
Builder()
|
||||
}
|
||||
|
||||
@ -182,11 +255,7 @@ func (wm *OrgLDAPIDPWriteModel) NewChangedEvent(
|
||||
if len(changes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
changeEvent, err := org.NewLDAPIDPChangedEvent(ctx, aggregate, id, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return changeEvent, nil
|
||||
return org.NewLDAPIDPChangedEvent(ctx, aggregate, id, oldName, changes)
|
||||
}
|
||||
|
||||
type OrgIDPRemoveWriteModel struct {
|
||||
@ -212,6 +281,10 @@ func (wm *OrgIDPRemoveWriteModel) Reduce() error {
|
||||
func (wm *OrgIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.OAuthIDPAddedEvent:
|
||||
wm.IDPRemoveWriteModel.AppendEvents(&e.OAuthIDPAddedEvent)
|
||||
case *org.OAuthIDPChangedEvent:
|
||||
wm.IDPRemoveWriteModel.AppendEvents(&e.OAuthIDPChangedEvent)
|
||||
case *org.GoogleIDPAddedEvent:
|
||||
wm.IDPRemoveWriteModel.AppendEvents(&e.GoogleIDPAddedEvent)
|
||||
case *org.GoogleIDPChangedEvent:
|
||||
@ -235,11 +308,14 @@ func (wm *OrgIDPRemoveWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
AggregateTypes(org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
org.OAuthIDPAddedEventType,
|
||||
org.OAuthIDPChangedEventType,
|
||||
org.GoogleIDPAddedEventType,
|
||||
org.GoogleIDPChangedEventType,
|
||||
org.LDAPIDPAddedEventType,
|
||||
org.LDAPIDPChangedEventType,
|
||||
org.IDPRemovedEventType,
|
||||
).
|
||||
EventData(map[string]interface{}{"id": wm.ID}).
|
||||
Builder()
|
||||
}
|
||||
|
@ -18,6 +18,552 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
provider GenericOAuthProvider
|
||||
}
|
||||
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: GenericOAuthProvider{},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid clientID",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid clientSecret",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid auth endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid token endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid user endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
eventPusherToEvents(
|
||||
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
id: "id1",
|
||||
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok all set",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
eventPusherToEvents(
|
||||
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
[]string{"user"},
|
||||
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: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
Scopes: []string{"user"},
|
||||
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.AddOrgGenericOAuthProvider(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_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
id string
|
||||
provider GenericOAuthProvider
|
||||
}
|
||||
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: GenericOAuthProvider{},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid name",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid clientID",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid auth endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid token endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid user endpoint",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errors.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
"clientID",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("clientSecret"),
|
||||
},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
),
|
||||
expectPush(
|
||||
eventPusherToEvents(
|
||||
func() eventstore.Command {
|
||||
t := true
|
||||
event, _ := org.NewOAuthIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
[]idp.OAuthIDPChanges{
|
||||
idp.ChangeOAuthName("new name"),
|
||||
idp.ChangeOAuthClientID("clientID2"),
|
||||
idp.ChangeOAuthClientSecret(&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("newSecret"),
|
||||
}),
|
||||
idp.ChangeOAuthAuthorizationEndpoint("new auth"),
|
||||
idp.ChangeOAuthTokenEndpoint("new token"),
|
||||
idp.ChangeOAuthUserEndpoint("new user"),
|
||||
idp.ChangeOAuthScopes([]string{"openid", "profile"}),
|
||||
idp.ChangeOAuthOptions(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: GenericOAuthProvider{
|
||||
Name: "new name",
|
||||
ClientID: "clientID2",
|
||||
ClientSecret: "newSecret",
|
||||
AuthorizationEndpoint: "new auth",
|
||||
TokenEndpoint: "new token",
|
||||
UserEndpoint: "new user",
|
||||
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.UpdateOrgGenericOAuthProvider(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
|
||||
@ -283,7 +829,7 @@ func TestCommandSide_UpdateOrgGoogleIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{},
|
||||
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -907,7 +1453,7 @@ func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{},
|
||||
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -33,6 +33,7 @@ type IDPTemplate struct {
|
||||
IsLinkingAllowed bool
|
||||
IsAutoCreation bool
|
||||
IsAutoUpdate bool
|
||||
*OAuthIDPTemplate
|
||||
*GoogleIDPTemplate
|
||||
*LDAPIDPTemplate
|
||||
}
|
||||
@ -42,6 +43,16 @@ type IDPTemplates struct {
|
||||
Templates []*IDPTemplate
|
||||
}
|
||||
|
||||
type OAuthIDPTemplate struct {
|
||||
IDPID string
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
AuthorizationEndpoint string
|
||||
TokenEndpoint string
|
||||
UserEndpoint string
|
||||
Scopes database.StringArray
|
||||
}
|
||||
|
||||
type GoogleIDPTemplate struct {
|
||||
IDPID string
|
||||
ClientID string
|
||||
@ -129,6 +140,45 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
oauthIdpTemplateTable = table{
|
||||
name: projection.IDPTemplateOAuthTable,
|
||||
instanceIDCol: projection.OAuthInstanceIDCol,
|
||||
}
|
||||
OAuthIDCol = Column{
|
||||
name: projection.OAuthIDCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
OAuthInstanceIDCol = Column{
|
||||
name: projection.OAuthInstanceIDCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
OAuthClientIDCol = Column{
|
||||
name: projection.OAuthClientIDCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
OAuthClientSecretCol = Column{
|
||||
name: projection.OAuthClientSecretCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
OAuthAuthorizationEndpointCol = Column{
|
||||
name: projection.OAuthAuthorizationEndpointCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
OAuthTokenEndpointCol = Column{
|
||||
name: projection.OAuthTokenEndpointCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
OAuthUserEndpointCol = Column{
|
||||
name: projection.OAuthUserEndpointCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
OAuthScopesCol = Column{
|
||||
name: projection.OAuthScopesCol,
|
||||
table: oauthIdpTemplateTable,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
googleIdpTemplateTable = table{
|
||||
name: projection.IDPTemplateGoogleTable,
|
||||
@ -370,10 +420,20 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
||||
IDPTemplateIsLinkingAllowedCol.identifier(),
|
||||
IDPTemplateIsAutoCreationCol.identifier(),
|
||||
IDPTemplateIsAutoUpdateCol.identifier(),
|
||||
// oauth
|
||||
OAuthIDCol.identifier(),
|
||||
OAuthClientIDCol.identifier(),
|
||||
OAuthClientSecretCol.identifier(),
|
||||
OAuthAuthorizationEndpointCol.identifier(),
|
||||
OAuthTokenEndpointCol.identifier(),
|
||||
OAuthUserEndpointCol.identifier(),
|
||||
OAuthScopesCol.identifier(),
|
||||
// google
|
||||
GoogleIDCol.identifier(),
|
||||
GoogleClientIDCol.identifier(),
|
||||
GoogleClientSecretCol.identifier(),
|
||||
GoogleScopesCol.identifier(),
|
||||
// ldap
|
||||
LDAPIDCol.identifier(),
|
||||
LDAPHostCol.identifier(),
|
||||
LDAPPortCol.identifier(),
|
||||
@ -397,6 +457,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
||||
LDAPAvatarURLAttributeCol.identifier(),
|
||||
LDAPProfileAttributeCol.identifier(),
|
||||
).From(idpTemplateTable.identifier()).
|
||||
LeftJoin(join(OAuthIDCol, IDPTemplateIDCol)).
|
||||
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
|
||||
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
@ -405,6 +466,14 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
||||
|
||||
name := sql.NullString{}
|
||||
|
||||
oauthID := sql.NullString{}
|
||||
oauthClientID := sql.NullString{}
|
||||
oauthClientSecret := new(crypto.CryptoValue)
|
||||
oauthAuthorizationEndpoint := sql.NullString{}
|
||||
oauthTokenEndpoint := sql.NullString{}
|
||||
oauthUserEndpoint := sql.NullString{}
|
||||
oauthScopes := database.StringArray{}
|
||||
|
||||
googleID := sql.NullString{}
|
||||
googleClientID := sql.NullString{}
|
||||
googleClientSecret := new(crypto.CryptoValue)
|
||||
@ -447,10 +516,20 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
||||
&idpTemplate.IsLinkingAllowed,
|
||||
&idpTemplate.IsAutoCreation,
|
||||
&idpTemplate.IsAutoUpdate,
|
||||
// oauth
|
||||
&oauthID,
|
||||
&oauthClientID,
|
||||
&oauthClientSecret,
|
||||
&oauthAuthorizationEndpoint,
|
||||
&oauthTokenEndpoint,
|
||||
&oauthUserEndpoint,
|
||||
&oauthScopes,
|
||||
// google
|
||||
&googleID,
|
||||
&googleClientID,
|
||||
&googleClientSecret,
|
||||
&googleScopes,
|
||||
// ldap
|
||||
&ldapID,
|
||||
&ldapHost,
|
||||
&ldapPort,
|
||||
@ -483,6 +562,17 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
||||
|
||||
idpTemplate.Name = name.String
|
||||
|
||||
if oauthID.Valid {
|
||||
idpTemplate.OAuthIDPTemplate = &OAuthIDPTemplate{
|
||||
IDPID: oauthID.String,
|
||||
ClientID: oauthClientID.String,
|
||||
ClientSecret: oauthClientSecret,
|
||||
AuthorizationEndpoint: oauthAuthorizationEndpoint.String,
|
||||
TokenEndpoint: oauthTokenEndpoint.String,
|
||||
UserEndpoint: oauthUserEndpoint.String,
|
||||
Scopes: oauthScopes,
|
||||
}
|
||||
}
|
||||
if googleID.Valid {
|
||||
idpTemplate.GoogleIDPTemplate = &GoogleIDPTemplate{
|
||||
IDPID: googleID.String,
|
||||
@ -490,7 +580,8 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
||||
ClientSecret: googleClientSecret,
|
||||
Scopes: googleScopes,
|
||||
}
|
||||
} else if ldapID.Valid {
|
||||
}
|
||||
if ldapID.Valid {
|
||||
idpTemplate.LDAPIDPTemplate = &LDAPIDPTemplate{
|
||||
IDPID: ldapID.String,
|
||||
Host: ldapHost.String,
|
||||
@ -538,10 +629,20 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
|
||||
IDPTemplateIsLinkingAllowedCol.identifier(),
|
||||
IDPTemplateIsAutoCreationCol.identifier(),
|
||||
IDPTemplateIsAutoUpdateCol.identifier(),
|
||||
// oauth
|
||||
OAuthIDCol.identifier(),
|
||||
OAuthClientIDCol.identifier(),
|
||||
OAuthClientSecretCol.identifier(),
|
||||
OAuthAuthorizationEndpointCol.identifier(),
|
||||
OAuthTokenEndpointCol.identifier(),
|
||||
OAuthUserEndpointCol.identifier(),
|
||||
OAuthScopesCol.identifier(),
|
||||
// google
|
||||
GoogleIDCol.identifier(),
|
||||
GoogleClientIDCol.identifier(),
|
||||
GoogleClientSecretCol.identifier(),
|
||||
GoogleScopesCol.identifier(),
|
||||
// ldap
|
||||
LDAPIDCol.identifier(),
|
||||
LDAPHostCol.identifier(),
|
||||
LDAPPortCol.identifier(),
|
||||
@ -566,6 +667,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
|
||||
LDAPProfileAttributeCol.identifier(),
|
||||
countColumn.identifier(),
|
||||
).From(idpTemplateTable.identifier()).
|
||||
LeftJoin(join(OAuthIDCol, IDPTemplateIDCol)).
|
||||
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
|
||||
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
@ -577,6 +679,14 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
|
||||
|
||||
name := sql.NullString{}
|
||||
|
||||
oauthID := sql.NullString{}
|
||||
oauthClientID := sql.NullString{}
|
||||
oauthClientSecret := new(crypto.CryptoValue)
|
||||
oauthAuthorizationEndpoint := sql.NullString{}
|
||||
oauthTokenEndpoint := sql.NullString{}
|
||||
oauthUserEndpoint := sql.NullString{}
|
||||
oauthScopes := database.StringArray{}
|
||||
|
||||
googleID := sql.NullString{}
|
||||
googleClientID := sql.NullString{}
|
||||
googleClientSecret := new(crypto.CryptoValue)
|
||||
@ -619,10 +729,20 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
|
||||
&idpTemplate.IsLinkingAllowed,
|
||||
&idpTemplate.IsAutoCreation,
|
||||
&idpTemplate.IsAutoUpdate,
|
||||
// oauth
|
||||
&oauthID,
|
||||
&oauthClientID,
|
||||
&oauthClientSecret,
|
||||
&oauthAuthorizationEndpoint,
|
||||
&oauthTokenEndpoint,
|
||||
&oauthUserEndpoint,
|
||||
&oauthScopes,
|
||||
// google
|
||||
&googleID,
|
||||
&googleClientID,
|
||||
&googleClientSecret,
|
||||
&googleScopes,
|
||||
// ldap
|
||||
&ldapID,
|
||||
&ldapHost,
|
||||
&ldapPort,
|
||||
@ -654,6 +774,17 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
|
||||
|
||||
idpTemplate.Name = name.String
|
||||
|
||||
if oauthID.Valid {
|
||||
idpTemplate.OAuthIDPTemplate = &OAuthIDPTemplate{
|
||||
IDPID: oauthID.String,
|
||||
ClientID: oauthClientID.String,
|
||||
ClientSecret: oauthClientSecret,
|
||||
AuthorizationEndpoint: oauthAuthorizationEndpoint.String,
|
||||
TokenEndpoint: oauthTokenEndpoint.String,
|
||||
UserEndpoint: oauthUserEndpoint.String,
|
||||
Scopes: oauthScopes,
|
||||
}
|
||||
}
|
||||
if googleID.Valid {
|
||||
idpTemplate.GoogleIDPTemplate = &GoogleIDPTemplate{
|
||||
IDPID: googleID.String,
|
||||
@ -661,7 +792,8 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
|
||||
ClientSecret: googleClientSecret,
|
||||
Scopes: googleScopes,
|
||||
}
|
||||
} else if ldapID.Valid {
|
||||
}
|
||||
if ldapID.Valid {
|
||||
idpTemplate.LDAPIDPTemplate = &LDAPIDPTemplate{
|
||||
IDPID: ldapID.String,
|
||||
Host: ldapHost.String,
|
||||
|
@ -28,10 +28,20 @@ var (
|
||||
` projections.idp_templates.is_linking_allowed,` +
|
||||
` projections.idp_templates.is_auto_creation,` +
|
||||
` projections.idp_templates.is_auto_update,` +
|
||||
// oauth
|
||||
` projections.idp_templates_oauth.idp_id,` +
|
||||
` projections.idp_templates_oauth.client_id,` +
|
||||
` projections.idp_templates_oauth.client_secret,` +
|
||||
` projections.idp_templates_oauth.authorization_endpoint,` +
|
||||
` projections.idp_templates_oauth.token_endpoint,` +
|
||||
` projections.idp_templates_oauth.user_endpoint,` +
|
||||
` projections.idp_templates_oauth.scopes,` +
|
||||
// google
|
||||
` projections.idp_templates_google.idp_id,` +
|
||||
` projections.idp_templates_google.client_id,` +
|
||||
` projections.idp_templates_google.client_secret,` +
|
||||
` projections.idp_templates_google.scopes,` +
|
||||
// ldap
|
||||
` projections.idp_templates_ldap.idp_id,` +
|
||||
` projections.idp_templates_ldap.host,` +
|
||||
` projections.idp_templates_ldap.port,` +
|
||||
@ -55,6 +65,7 @@ var (
|
||||
` projections.idp_templates_ldap.avatar_url_attribute,` +
|
||||
` projections.idp_templates_ldap.profile_attribute` +
|
||||
` FROM projections.idp_templates` +
|
||||
` LEFT JOIN projections.idp_templates_oauth ON projections.idp_templates.id = projections.idp_templates_oauth.idp_id AND projections.idp_templates.instance_id = projections.idp_templates_oauth.instance_id` +
|
||||
` LEFT JOIN projections.idp_templates_google ON projections.idp_templates.id = projections.idp_templates_google.idp_id AND projections.idp_templates.instance_id = projections.idp_templates_google.instance_id` +
|
||||
` LEFT JOIN projections.idp_templates_ldap ON projections.idp_templates.id = projections.idp_templates_ldap.idp_id AND projections.idp_templates.instance_id = projections.idp_templates_ldap.instance_id`
|
||||
idpTemplateCols = []string{
|
||||
@ -71,6 +82,14 @@ var (
|
||||
"is_linking_allowed",
|
||||
"is_auto_creation",
|
||||
"is_auto_update",
|
||||
// oauth config
|
||||
"idp_id",
|
||||
"client_id",
|
||||
"client_secret",
|
||||
"authorization_endpoint",
|
||||
"token_endpoint",
|
||||
"user_endpoint",
|
||||
"scopes",
|
||||
// google config
|
||||
"idp_id",
|
||||
"client_id",
|
||||
@ -113,10 +132,20 @@ var (
|
||||
` projections.idp_templates.is_linking_allowed,` +
|
||||
` projections.idp_templates.is_auto_creation,` +
|
||||
` projections.idp_templates.is_auto_update,` +
|
||||
// oauth
|
||||
` projections.idp_templates_oauth.idp_id,` +
|
||||
` projections.idp_templates_oauth.client_id,` +
|
||||
` projections.idp_templates_oauth.client_secret,` +
|
||||
` projections.idp_templates_oauth.authorization_endpoint,` +
|
||||
` projections.idp_templates_oauth.token_endpoint,` +
|
||||
` projections.idp_templates_oauth.user_endpoint,` +
|
||||
` projections.idp_templates_oauth.scopes,` +
|
||||
// google
|
||||
` projections.idp_templates_google.idp_id,` +
|
||||
` projections.idp_templates_google.client_id,` +
|
||||
` projections.idp_templates_google.client_secret,` +
|
||||
` projections.idp_templates_google.scopes,` +
|
||||
// ldap
|
||||
` projections.idp_templates_ldap.idp_id,` +
|
||||
` projections.idp_templates_ldap.host,` +
|
||||
` projections.idp_templates_ldap.port,` +
|
||||
@ -141,6 +170,7 @@ var (
|
||||
` projections.idp_templates_ldap.profile_attribute,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.idp_templates` +
|
||||
` LEFT JOIN projections.idp_templates_oauth ON projections.idp_templates.id = projections.idp_templates_oauth.idp_id AND projections.idp_templates.instance_id = projections.idp_templates_oauth.instance_id` +
|
||||
` LEFT JOIN projections.idp_templates_google ON projections.idp_templates.id = projections.idp_templates_google.idp_id AND projections.idp_templates.instance_id = projections.idp_templates_google.instance_id` +
|
||||
` LEFT JOIN projections.idp_templates_ldap ON projections.idp_templates.id = projections.idp_templates_ldap.idp_id AND projections.idp_templates.instance_id = projections.idp_templates_ldap.instance_id`
|
||||
idpTemplatesCols = []string{
|
||||
@ -157,6 +187,14 @@ var (
|
||||
"is_linking_allowed",
|
||||
"is_auto_creation",
|
||||
"is_auto_update",
|
||||
// oauth config
|
||||
"idp_id",
|
||||
"client_id",
|
||||
"client_secret",
|
||||
"authorization_endpoint",
|
||||
"token_endpoint",
|
||||
"user_endpoint",
|
||||
"scopes",
|
||||
// google config
|
||||
"idp_id",
|
||||
"client_id",
|
||||
@ -218,7 +256,91 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
},
|
||||
object: (*IDPTemplate)(nil),
|
||||
},
|
||||
|
||||
{
|
||||
name: "prepareIDPTemplateByIDQuery oauth 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.IDPTypeOAuth,
|
||||
domain.IdentityProviderTypeOrg,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
"idp-id",
|
||||
"client_id",
|
||||
nil,
|
||||
"authorization",
|
||||
"token",
|
||||
"user",
|
||||
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.IDPTypeOAuth,
|
||||
OwnerType: domain.IdentityProviderTypeOrg,
|
||||
IsCreationAllowed: true,
|
||||
IsLinkingAllowed: true,
|
||||
IsAutoCreation: true,
|
||||
IsAutoUpdate: true,
|
||||
OAuthIDPTemplate: &OAuthIDPTemplate{
|
||||
IDPID: "idp-id",
|
||||
ClientID: "client_id",
|
||||
ClientSecret: nil,
|
||||
AuthorizationEndpoint: "authorization",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
Scopes: []string{"profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareIDPTemplateByIDQuery google idp",
|
||||
prepare: prepareIDPTemplateByIDQuery,
|
||||
@ -240,6 +362,14 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// google
|
||||
"idp-id",
|
||||
"client_id",
|
||||
@ -314,6 +444,14 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// google
|
||||
nil,
|
||||
nil,
|
||||
@ -407,6 +545,14 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// google config
|
||||
nil,
|
||||
nil,
|
||||
@ -511,6 +657,14 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// google config
|
||||
nil,
|
||||
nil,
|
||||
@ -613,6 +767,14 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// google config
|
||||
nil,
|
||||
nil,
|
||||
@ -690,6 +852,14 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// google config
|
||||
nil,
|
||||
nil,
|
||||
@ -733,6 +903,14 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
// google
|
||||
"idp-id-google",
|
||||
"client_id",
|
||||
@ -762,12 +940,63 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"idp-id-oauth",
|
||||
"ro",
|
||||
testNow,
|
||||
testNow,
|
||||
uint64(20211109),
|
||||
domain.IDPConfigStateActive,
|
||||
"idp-name",
|
||||
domain.IDPTypeOAuth,
|
||||
domain.IdentityProviderTypeOrg,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
// oauth
|
||||
"idp-id-oauth",
|
||||
"client_id",
|
||||
nil,
|
||||
"authorization",
|
||||
"token",
|
||||
"user",
|
||||
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: &IDPTemplates{
|
||||
SearchResponse: SearchResponse{
|
||||
Count: 2,
|
||||
Count: 3,
|
||||
},
|
||||
Templates: []*IDPTemplate{
|
||||
{
|
||||
@ -831,6 +1060,31 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
||||
Scopes: []string{"profile"},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
Sequence: 20211109,
|
||||
ResourceOwner: "ro",
|
||||
ID: "idp-id-oauth",
|
||||
State: domain.IDPStateActive,
|
||||
Name: "idp-name",
|
||||
Type: domain.IDPTypeOAuth,
|
||||
OwnerType: domain.IdentityProviderTypeOrg,
|
||||
IsCreationAllowed: true,
|
||||
IsLinkingAllowed: true,
|
||||
IsAutoCreation: true,
|
||||
IsAutoUpdate: true,
|
||||
OAuthIDPTemplate: &OAuthIDPTemplate{
|
||||
IDPID: "idp-id-oauth",
|
||||
ClientID: "client_id",
|
||||
ClientSecret: nil,
|
||||
AuthorizationEndpoint: "authorization",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
Scopes: []string{"profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -17,9 +17,11 @@ import (
|
||||
|
||||
const (
|
||||
IDPTemplateTable = "projections.idp_templates"
|
||||
IDPTemplateOAuthTable = IDPTemplateTable + "_" + IDPTemplateOAuthSuffix
|
||||
IDPTemplateGoogleTable = IDPTemplateTable + "_" + IDPTemplateGoogleSuffix
|
||||
IDPTemplateLDAPTable = IDPTemplateTable + "_" + IDPTemplateLDAPSuffix
|
||||
|
||||
IDPTemplateOAuthSuffix = "oauth"
|
||||
IDPTemplateGoogleSuffix = "google"
|
||||
IDPTemplateLDAPSuffix = "ldap"
|
||||
|
||||
@ -39,6 +41,15 @@ const (
|
||||
IDPTemplateIsAutoCreationCol = "is_auto_creation"
|
||||
IDPTemplateIsAutoUpdateCol = "is_auto_update"
|
||||
|
||||
OAuthIDCol = "idp_id"
|
||||
OAuthInstanceIDCol = "instance_id"
|
||||
OAuthClientIDCol = "client_id"
|
||||
OAuthClientSecretCol = "client_secret"
|
||||
OAuthAuthorizationEndpointCol = "authorization_endpoint"
|
||||
OAuthTokenEndpointCol = "token_endpoint"
|
||||
OAuthUserEndpointCol = "user_endpoint"
|
||||
OAuthScopesCol = "scopes"
|
||||
|
||||
GoogleIDCol = "idp_id"
|
||||
GoogleInstanceIDCol = "instance_id"
|
||||
GoogleClientIDCol = "client_id"
|
||||
@ -100,6 +111,20 @@ func newIDPTemplateProjection(ctx context.Context, config crdb.StatementHandlerC
|
||||
crdb.WithIndex(crdb.NewIndex("resource_owner", []string{IDPTemplateResourceOwnerCol})),
|
||||
crdb.WithIndex(crdb.NewIndex("owner_removed", []string{IDPTemplateOwnerRemovedCol})),
|
||||
),
|
||||
crdb.NewSuffixedTable([]*crdb.Column{
|
||||
crdb.NewColumn(OAuthIDCol, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(OAuthInstanceIDCol, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(OAuthClientIDCol, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(OAuthClientSecretCol, crdb.ColumnTypeJSONB),
|
||||
crdb.NewColumn(OAuthAuthorizationEndpointCol, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(OAuthTokenEndpointCol, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(OAuthUserEndpointCol, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(OAuthScopesCol, crdb.ColumnTypeTextArray, crdb.Nullable()),
|
||||
},
|
||||
crdb.NewPrimaryKey(OAuthInstanceIDCol, OAuthIDCol),
|
||||
IDPTemplateOAuthSuffix,
|
||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys()),
|
||||
),
|
||||
crdb.NewSuffixedTable([]*crdb.Column{
|
||||
crdb.NewColumn(GoogleIDCol, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(GoogleInstanceIDCol, crdb.ColumnTypeText),
|
||||
@ -150,6 +175,14 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
|
||||
{
|
||||
Aggregate: instance.AggregateType,
|
||||
EventRedusers: []handler.EventReducer{
|
||||
{
|
||||
Event: instance.OAuthIDPAddedEventType,
|
||||
Reduce: p.reduceOAuthIDPAdded,
|
||||
},
|
||||
{
|
||||
Event: instance.OAuthIDPChangedEventType,
|
||||
Reduce: p.reduceOAuthIDPChanged,
|
||||
},
|
||||
{
|
||||
Event: instance.GoogleIDPAddedEventType,
|
||||
Reduce: p.reduceGoogleIDPAdded,
|
||||
@ -179,6 +212,14 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
|
||||
{
|
||||
Aggregate: org.AggregateType,
|
||||
EventRedusers: []handler.EventReducer{
|
||||
{
|
||||
Event: org.OAuthIDPAddedEventType,
|
||||
Reduce: p.reduceOAuthIDPAdded,
|
||||
},
|
||||
{
|
||||
Event: org.OAuthIDPChangedEventType,
|
||||
Reduce: p.reduceOAuthIDPChanged,
|
||||
},
|
||||
{
|
||||
Event: org.GoogleIDPAddedEventType,
|
||||
Reduce: p.reduceGoogleIDPAdded,
|
||||
@ -208,6 +249,97 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *idpTemplateProjection) reduceOAuthIDPAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||
var idpEvent idp.OAuthIDPAddedEvent
|
||||
var idpOwnerType domain.IdentityProviderType
|
||||
switch e := event.(type) {
|
||||
case *org.OAuthIDPAddedEvent:
|
||||
idpEvent = e.OAuthIDPAddedEvent
|
||||
idpOwnerType = domain.IdentityProviderTypeOrg
|
||||
case *instance.OAuthIDPAddedEvent:
|
||||
idpEvent = e.OAuthIDPAddedEvent
|
||||
idpOwnerType = domain.IdentityProviderTypeSystem
|
||||
default:
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-ap9ihb", "reduce.wrong.event.type %v", []eventstore.EventType{org.OAuthIDPAddedEventType, instance.OAuthIDPAddedEventType})
|
||||
}
|
||||
|
||||
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.IDPTypeOAuth),
|
||||
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(OAuthIDCol, idpEvent.ID),
|
||||
handler.NewCol(OAuthInstanceIDCol, idpEvent.Aggregate().InstanceID),
|
||||
handler.NewCol(OAuthClientIDCol, idpEvent.ClientID),
|
||||
handler.NewCol(OAuthClientSecretCol, idpEvent.ClientSecret),
|
||||
handler.NewCol(OAuthAuthorizationEndpointCol, idpEvent.AuthorizationEndpoint),
|
||||
handler.NewCol(OAuthTokenEndpointCol, idpEvent.TokenEndpoint),
|
||||
handler.NewCol(OAuthUserEndpointCol, idpEvent.UserEndpoint),
|
||||
handler.NewCol(OAuthScopesCol, database.StringArray(idpEvent.Scopes)),
|
||||
},
|
||||
crdb.WithTableSuffix(IDPTemplateOAuthSuffix),
|
||||
),
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *idpTemplateProjection) reduceOAuthIDPChanged(event eventstore.Event) (*handler.Statement, error) {
|
||||
var idpEvent idp.OAuthIDPChangedEvent
|
||||
switch e := event.(type) {
|
||||
case *org.OAuthIDPChangedEvent:
|
||||
idpEvent = e.OAuthIDPChangedEvent
|
||||
case *instance.OAuthIDPChangedEvent:
|
||||
idpEvent = e.OAuthIDPChangedEvent
|
||||
default:
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-p1582ks", "reduce.wrong.event.type %v", []eventstore.EventType{org.OAuthIDPChangedEventType, instance.OAuthIDPChangedEventType})
|
||||
}
|
||||
|
||||
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),
|
||||
},
|
||||
),
|
||||
)
|
||||
oauthCols := reduceOAuthIDPChangedColumns(idpEvent)
|
||||
if len(oauthCols) > 0 {
|
||||
ops = append(ops,
|
||||
crdb.AddUpdateStatement(
|
||||
oauthCols,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(OAuthIDCol, idpEvent.ID),
|
||||
handler.NewCond(OAuthInstanceIDCol, idpEvent.Aggregate().InstanceID),
|
||||
},
|
||||
crdb.WithTableSuffix(IDPTemplateOAuthSuffix),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return crdb.NewMultiStatement(
|
||||
&idpEvent,
|
||||
ops...,
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *idpTemplateProjection) reduceGoogleIDPAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||
var idpEvent idp.GoogleIDPAddedEvent
|
||||
var idpOwnerType domain.IdentityProviderType
|
||||
@ -466,6 +598,29 @@ func reduceIDPChangedTemplateColumns(name *string, creationDate time.Time, seque
|
||||
)
|
||||
}
|
||||
|
||||
func reduceOAuthIDPChangedColumns(idpEvent idp.OAuthIDPChangedEvent) []handler.Column {
|
||||
oauthCols := make([]handler.Column, 0, 6)
|
||||
if idpEvent.ClientID != nil {
|
||||
oauthCols = append(oauthCols, handler.NewCol(OAuthClientIDCol, *idpEvent.ClientID))
|
||||
}
|
||||
if idpEvent.ClientSecret != nil {
|
||||
oauthCols = append(oauthCols, handler.NewCol(OAuthClientSecretCol, *idpEvent.ClientSecret))
|
||||
}
|
||||
if idpEvent.AuthorizationEndpoint != nil {
|
||||
oauthCols = append(oauthCols, handler.NewCol(OAuthAuthorizationEndpointCol, *idpEvent.AuthorizationEndpoint))
|
||||
}
|
||||
if idpEvent.TokenEndpoint != nil {
|
||||
oauthCols = append(oauthCols, handler.NewCol(OAuthTokenEndpointCol, *idpEvent.TokenEndpoint))
|
||||
}
|
||||
if idpEvent.UserEndpoint != nil {
|
||||
oauthCols = append(oauthCols, handler.NewCol(OAuthUserEndpointCol, *idpEvent.UserEndpoint))
|
||||
}
|
||||
if idpEvent.Scopes != nil {
|
||||
oauthCols = append(oauthCols, handler.NewCol(OAuthScopesCol, database.StringArray(idpEvent.Scopes)))
|
||||
}
|
||||
return oauthCols
|
||||
}
|
||||
|
||||
func reduceGoogleIDPChangedColumns(idpEvent idp.GoogleIDPChangedEvent) []handler.Column {
|
||||
googleCols := make([]handler.Column, 0, 3)
|
||||
if idpEvent.ClientID != nil {
|
||||
|
@ -125,6 +125,276 @@ func TestIDPTemplateProjection_reducesRemove(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDPTemplateProjection_reducesOAuth(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 reduceOAuthIDPAdded",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(instance.OAuthIDPAddedEventType),
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"id": "idp-id",
|
||||
"name": "custom-zitadel-instance",
|
||||
"client_id": "client_id",
|
||||
"client_secret": {
|
||||
"cryptoType": 0,
|
||||
"algorithm": "RSA-265",
|
||||
"keyId": "key-id"
|
||||
},
|
||||
"authorizationEndpoint": "auth",
|
||||
"tokenEndpoint": "token",
|
||||
"userEndpoint": "user",
|
||||
"scopes": ["profile"],
|
||||
"isCreationAllowed": true,
|
||||
"isLinkingAllowed": true,
|
||||
"isAutoCreation": true,
|
||||
"isAutoUpdate": true
|
||||
}`),
|
||||
), instance.OAuthIDPAddedEventMapper),
|
||||
},
|
||||
reduce: (&idpTemplateProjection{}).reduceOAuthIDPAdded,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("instance"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.idp_templates (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)",
|
||||
expectedArgs: []interface{}{
|
||||
"idp-id",
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
domain.IDPStateActive,
|
||||
"custom-zitadel-instance",
|
||||
domain.IdentityProviderTypeSystem,
|
||||
domain.IDPTypeOAuth,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.idp_templates_oauth (idp_id, instance_id, client_id, client_secret, authorization_endpoint, token_endpoint, user_endpoint, scopes) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
|
||||
expectedArgs: []interface{}{
|
||||
"idp-id",
|
||||
"instance-id",
|
||||
"client_id",
|
||||
anyArg{},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
database.StringArray{"profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org reduceOAuthIDPAdded",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(org.OAuthIDPAddedEventType),
|
||||
org.AggregateType,
|
||||
[]byte(`{
|
||||
"id": "idp-id",
|
||||
"name": "custom-zitadel-instance",
|
||||
"client_id": "client_id",
|
||||
"client_secret": {
|
||||
"cryptoType": 0,
|
||||
"algorithm": "RSA-265",
|
||||
"keyId": "key-id"
|
||||
},
|
||||
"authorizationEndpoint": "auth",
|
||||
"tokenEndpoint": "token",
|
||||
"userEndpoint": "user",
|
||||
"scopes": ["profile"],
|
||||
"isCreationAllowed": true,
|
||||
"isLinkingAllowed": true,
|
||||
"isAutoCreation": true,
|
||||
"isAutoUpdate": true
|
||||
}`),
|
||||
), org.OAuthIDPAddedEventMapper),
|
||||
},
|
||||
reduce: (&idpTemplateProjection{}).reduceOAuthIDPAdded,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("org"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.idp_templates (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)",
|
||||
expectedArgs: []interface{}{
|
||||
"idp-id",
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
domain.IDPStateActive,
|
||||
"custom-zitadel-instance",
|
||||
domain.IdentityProviderTypeOrg,
|
||||
domain.IDPTypeOAuth,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.idp_templates_oauth (idp_id, instance_id, client_id, client_secret, authorization_endpoint, token_endpoint, user_endpoint, scopes) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
|
||||
expectedArgs: []interface{}{
|
||||
"idp-id",
|
||||
"instance-id",
|
||||
"client_id",
|
||||
anyArg{},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
database.StringArray{"profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance reduceOAuthIDPChanged minimal",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(instance.OAuthIDPChangedEventType),
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"id": "idp-id",
|
||||
"isCreationAllowed": true,
|
||||
"client_id": "id"
|
||||
}`),
|
||||
), instance.OAuthIDPChangedEventMapper),
|
||||
},
|
||||
reduce: (&idpTemplateProjection{}).reduceOAuthIDPChanged,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("instance"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.idp_templates SET (is_creation_allowed, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
true,
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
"idp-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.idp_templates_oauth SET client_id = $1 WHERE (idp_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"id",
|
||||
"idp-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance reduceOAuthIDPChanged",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(instance.OAuthIDPChangedEventType),
|
||||
instance.AggregateType,
|
||||
[]byte(`{
|
||||
"id": "idp-id",
|
||||
"name": "custom-zitadel-instance",
|
||||
"client_id": "client_id",
|
||||
"client_secret": {
|
||||
"cryptoType": 0,
|
||||
"algorithm": "RSA-265",
|
||||
"keyId": "key-id"
|
||||
},
|
||||
"authorizationEndpoint": "auth",
|
||||
"tokenEndpoint": "token",
|
||||
"userEndpoint": "user",
|
||||
"scopes": ["profile"],
|
||||
"isCreationAllowed": true,
|
||||
"isLinkingAllowed": true,
|
||||
"isAutoCreation": true,
|
||||
"isAutoUpdate": true
|
||||
}`),
|
||||
), instance.OAuthIDPChangedEventMapper),
|
||||
},
|
||||
reduce: (&idpTemplateProjection{}).reduceOAuthIDPChanged,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("instance"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.idp_templates 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)",
|
||||
expectedArgs: []interface{}{
|
||||
"custom-zitadel-instance",
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
"idp-id",
|
||||
"instance-id",
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.idp_templates_oauth SET (client_id, client_secret, authorization_endpoint, token_endpoint, user_endpoint, scopes) = ($1, $2, $3, $4, $5, $6) WHERE (idp_id = $7) AND (instance_id = $8)",
|
||||
expectedArgs: []interface{}{
|
||||
"client_id",
|
||||
anyArg{},
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
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
|
||||
|
@ -47,8 +47,8 @@ func (o *Options) ReduceChanges(changes OptionChanges) {
|
||||
if changes.IsLinkingAllowed != nil {
|
||||
o.IsLinkingAllowed = *changes.IsLinkingAllowed
|
||||
}
|
||||
if changes.IsAutoUpdate != nil {
|
||||
o.IsAutoUpdate = *changes.IsAutoUpdate
|
||||
if changes.IsAutoCreation != nil {
|
||||
o.IsAutoCreation = *changes.IsAutoCreation
|
||||
}
|
||||
if changes.IsAutoUpdate != nil {
|
||||
o.IsAutoUpdate = *changes.IsAutoUpdate
|
||||
|
173
internal/repository/idp/oauth.go
Normal file
173
internal/repository/idp/oauth.go
Normal file
@ -0,0 +1,173 @@
|
||||
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 OAuthIDPAddedEvent 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"`
|
||||
AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"`
|
||||
TokenEndpoint string `json:"tokenEndpoint,omitempty"`
|
||||
UserEndpoint string `json:"userEndpoint,omitempty"`
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
Options
|
||||
}
|
||||
|
||||
func NewOAuthIDPAddedEvent(
|
||||
base *eventstore.BaseEvent,
|
||||
id,
|
||||
name,
|
||||
clientID string,
|
||||
clientSecret *crypto.CryptoValue,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
scopes []string,
|
||||
options Options,
|
||||
) *OAuthIDPAddedEvent {
|
||||
return &OAuthIDPAddedEvent{
|
||||
BaseEvent: *base,
|
||||
ID: id,
|
||||
Name: name,
|
||||
ClientID: clientID,
|
||||
ClientSecret: clientSecret,
|
||||
AuthorizationEndpoint: authorizationEndpoint,
|
||||
TokenEndpoint: tokenEndpoint,
|
||||
UserEndpoint: userEndpoint,
|
||||
Scopes: scopes,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *OAuthIDPAddedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *OAuthIDPAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func OAuthIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e := &OAuthIDPAddedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(event.Data, e)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "IDP-Et1dq", "unable to unmarshal event")
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
type OAuthIDPChangedEvent 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"`
|
||||
AuthorizationEndpoint *string `json:"authorizationEndpoint,omitempty"`
|
||||
TokenEndpoint *string `json:"tokenEndpoint,omitempty"`
|
||||
UserEndpoint *string `json:"userEndpoint,omitempty"`
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
OptionChanges
|
||||
}
|
||||
|
||||
func NewOAuthIDPChangedEvent(
|
||||
base *eventstore.BaseEvent,
|
||||
id string,
|
||||
changes []OAuthIDPChanges,
|
||||
) (*OAuthIDPChangedEvent, error) {
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "IDP-BH3dl", "Errors.NoChangesFound")
|
||||
}
|
||||
changedEvent := &OAuthIDPChangedEvent{
|
||||
BaseEvent: *base,
|
||||
ID: id,
|
||||
}
|
||||
for _, change := range changes {
|
||||
change(changedEvent)
|
||||
}
|
||||
return changedEvent, nil
|
||||
}
|
||||
|
||||
type OAuthIDPChanges func(*OAuthIDPChangedEvent)
|
||||
|
||||
func ChangeOAuthName(name string) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.Name = &name
|
||||
}
|
||||
}
|
||||
func ChangeOAuthClientID(clientID string) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.ClientID = &clientID
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOAuthClientSecret(clientSecret *crypto.CryptoValue) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.ClientSecret = clientSecret
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOAuthOptions(options OptionChanges) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.OptionChanges = options
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOAuthAuthorizationEndpoint(authorizationEndpoint string) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.AuthorizationEndpoint = &authorizationEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOAuthTokenEndpoint(tokenEndpoint string) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.TokenEndpoint = &tokenEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOAuthUserEndpoint(userEndpoint string) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.UserEndpoint = &userEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOAuthScopes(scopes []string) func(*OAuthIDPChangedEvent) {
|
||||
return func(e *OAuthIDPChangedEvent) {
|
||||
e.Scopes = scopes
|
||||
}
|
||||
}
|
||||
|
||||
func (e *OAuthIDPChangedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *OAuthIDPChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func OAuthIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e := &OAuthIDPChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(event.Data, e)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "IDP-SAf3gw", "unable to unmarshal event")
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
@ -70,6 +70,8 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(AggregateType, IDPOIDCConfigChangedEventType, IDPOIDCConfigChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, IDPJWTConfigAddedEventType, IDPJWTConfigAddedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, IDPJWTConfigChangedEventType, IDPJWTConfigChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, OAuthIDPAddedEventType, OAuthIDPAddedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, OAuthIDPChangedEventType, OAuthIDPChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, GoogleIDPAddedEventType, GoogleIDPAddedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, GoogleIDPChangedEventType, GoogleIDPChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, LDAPIDPAddedEventType, LDAPIDPAddedEventMapper).
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
OAuthIDPAddedEventType eventstore.EventType = "instance.idp.oauth.added"
|
||||
OAuthIDPChangedEventType eventstore.EventType = "instance.idp.oauth.changed"
|
||||
GoogleIDPAddedEventType eventstore.EventType = "instance.idp.google.added"
|
||||
GoogleIDPChangedEventType eventstore.EventType = "instance.idp.google.changed"
|
||||
LDAPIDPAddedEventType eventstore.EventType = "instance.idp.ldap.added"
|
||||
@ -17,6 +19,88 @@ const (
|
||||
IDPRemovedEventType eventstore.EventType = "instance.idp.removed"
|
||||
)
|
||||
|
||||
type OAuthIDPAddedEvent struct {
|
||||
idp.OAuthIDPAddedEvent
|
||||
}
|
||||
|
||||
func NewOAuthIDPAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id,
|
||||
name,
|
||||
clientID string,
|
||||
clientSecret *crypto.CryptoValue,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) *OAuthIDPAddedEvent {
|
||||
|
||||
return &OAuthIDPAddedEvent{
|
||||
OAuthIDPAddedEvent: *idp.NewOAuthIDPAddedEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
OAuthIDPAddedEventType,
|
||||
),
|
||||
id,
|
||||
name,
|
||||
clientID,
|
||||
clientSecret,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint,
|
||||
scopes,
|
||||
options,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func OAuthIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e, err := idp.OAuthIDPAddedEventMapper(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OAuthIDPAddedEvent{OAuthIDPAddedEvent: *e.(*idp.OAuthIDPAddedEvent)}, nil
|
||||
}
|
||||
|
||||
type OAuthIDPChangedEvent struct {
|
||||
idp.OAuthIDPChangedEvent
|
||||
}
|
||||
|
||||
func NewOAuthIDPChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
changes []idp.OAuthIDPChanges,
|
||||
) (*OAuthIDPChangedEvent, error) {
|
||||
|
||||
changedEvent, err := idp.NewOAuthIDPChangedEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
OAuthIDPChangedEventType,
|
||||
),
|
||||
id,
|
||||
changes,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &OAuthIDPChangedEvent{OAuthIDPChangedEvent: *changedEvent}, nil
|
||||
}
|
||||
|
||||
func OAuthIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e, err := idp.OAuthIDPChangedEventMapper(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OAuthIDPChangedEvent{OAuthIDPChangedEvent: *e.(*idp.OAuthIDPChangedEvent)}, nil
|
||||
}
|
||||
|
||||
type GoogleIDPAddedEvent struct {
|
||||
idp.GoogleIDPAddedEvent
|
||||
}
|
||||
|
@ -78,6 +78,8 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(AggregateType, IDPOIDCConfigChangedEventType, IDPOIDCConfigChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, IDPJWTConfigAddedEventType, IDPJWTConfigAddedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, IDPJWTConfigChangedEventType, IDPJWTConfigChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, OAuthIDPAddedEventType, OAuthIDPAddedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, OAuthIDPChangedEventType, OAuthIDPChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, GoogleIDPAddedEventType, GoogleIDPAddedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, GoogleIDPChangedEventType, GoogleIDPChangedEventMapper).
|
||||
RegisterFilterEventMapper(AggregateType, LDAPIDPAddedEventType, LDAPIDPAddedEventMapper).
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
OAuthIDPAddedEventType eventstore.EventType = "org.idp.oauth.added"
|
||||
OAuthIDPChangedEventType eventstore.EventType = "org.idp.oauth.changed"
|
||||
GoogleIDPAddedEventType eventstore.EventType = "org.idp.google.added"
|
||||
GoogleIDPChangedEventType eventstore.EventType = "org.idp.google.changed"
|
||||
LDAPIDPAddedEventType eventstore.EventType = "org.idp.ldap.added"
|
||||
@ -17,6 +19,88 @@ const (
|
||||
IDPRemovedEventType eventstore.EventType = "org.idp.removed"
|
||||
)
|
||||
|
||||
type OAuthIDPAddedEvent struct {
|
||||
idp.OAuthIDPAddedEvent
|
||||
}
|
||||
|
||||
func NewOAuthIDPAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id,
|
||||
name,
|
||||
clientID string,
|
||||
clientSecret *crypto.CryptoValue,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) *OAuthIDPAddedEvent {
|
||||
|
||||
return &OAuthIDPAddedEvent{
|
||||
OAuthIDPAddedEvent: *idp.NewOAuthIDPAddedEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
OAuthIDPAddedEventType,
|
||||
),
|
||||
id,
|
||||
name,
|
||||
clientID,
|
||||
clientSecret,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint,
|
||||
scopes,
|
||||
options,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func OAuthIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e, err := idp.OAuthIDPAddedEventMapper(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OAuthIDPAddedEvent{OAuthIDPAddedEvent: *e.(*idp.OAuthIDPAddedEvent)}, nil
|
||||
}
|
||||
|
||||
type OAuthIDPChangedEvent struct {
|
||||
idp.OAuthIDPChangedEvent
|
||||
}
|
||||
|
||||
func NewOAuthIDPChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
changes []idp.OAuthIDPChanges,
|
||||
) (*OAuthIDPChangedEvent, error) {
|
||||
|
||||
changedEvent, err := idp.NewOAuthIDPChangedEvent(
|
||||
eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
OAuthIDPChangedEventType,
|
||||
),
|
||||
id,
|
||||
changes,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &OAuthIDPChangedEvent{OAuthIDPChangedEvent: *changedEvent}, nil
|
||||
}
|
||||
|
||||
func OAuthIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e, err := idp.OAuthIDPChangedEventMapper(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OAuthIDPChangedEvent{OAuthIDPChangedEvent: *e.(*idp.OAuthIDPChangedEvent)}, nil
|
||||
}
|
||||
|
||||
type GoogleIDPAddedEvent struct {
|
||||
idp.GoogleIDPAddedEvent
|
||||
}
|
||||
|
@ -1248,6 +1248,30 @@ service AdminService {
|
||||
};
|
||||
}
|
||||
|
||||
// Add a new OAuth2 identity provider on the instance
|
||||
rpc AddGenericOAuthProvider(AddGenericOAuthProviderRequest) returns (AddGenericOAuthProviderResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/idps/oauth"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "iam.idp.write"
|
||||
};
|
||||
}
|
||||
|
||||
// Change an existing OAuth2 identity provider on the instance
|
||||
rpc UpdateGenericOAuthProvider(UpdateGenericOAuthProviderRequest) returns (UpdateGenericOAuthProviderResponse) {
|
||||
option (google.api.http) = {
|
||||
put: "/idps/oauth/{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) = {
|
||||
@ -4259,6 +4283,39 @@ message GetProviderByIDResponse {
|
||||
zitadel.idp.v1.Provider idp = 1;
|
||||
}
|
||||
|
||||
message AddGenericOAuthProviderRequest {
|
||||
string name = 1 [(validate.rules).string = {min_len: 1, 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}];
|
||||
string authorization_endpoint = 4 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string token_endpoint = 5 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string user_endpoint = 6 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
repeated string scopes = 7 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||
zitadel.idp.v1.Options provider_options = 8;
|
||||
}
|
||||
|
||||
message AddGenericOAuthProviderResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message UpdateGenericOAuthProviderRequest {
|
||||
string id = 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}];
|
||||
// client_secret will only be updated if provided
|
||||
string client_secret = 4 [(validate.rules).string = {max_len: 200}];
|
||||
string authorization_endpoint = 5 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string token_endpoint = 6 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string user_endpoint = 7 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
repeated string scopes = 8 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||
zitadel.idp.v1.Options provider_options = 9;
|
||||
}
|
||||
|
||||
message UpdateGenericOAuthProviderResponse {
|
||||
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}];
|
||||
|
@ -263,8 +263,16 @@ message ProviderConfig {
|
||||
oneof config {
|
||||
LDAPConfig ldap = 2;
|
||||
GoogleConfig google = 3;
|
||||
OAuthConfig oauth = 4;
|
||||
}
|
||||
}
|
||||
message OAuthConfig {
|
||||
string client_id = 1;
|
||||
string authorization_endpoint = 2;
|
||||
string token_endpoint = 3;
|
||||
string user_endpoint = 4;
|
||||
repeated string scopes = 5;
|
||||
}
|
||||
|
||||
message GoogleConfig {
|
||||
string client_id = 1;
|
||||
|
@ -4369,6 +4369,29 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
// Add a new OAuth2 identity provider in the organisation
|
||||
rpc AddGenericOAuthProvider(AddGenericOAuthProviderRequest) returns (AddGenericOAuthProviderResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/idps/oauth"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "org.idp.write"
|
||||
};
|
||||
}
|
||||
|
||||
// Change an existing OAuth2 identity provider in the organisation
|
||||
rpc UpdateGenericOAuthProvider(UpdateGenericOAuthProviderRequest) returns (UpdateGenericOAuthProviderResponse) {
|
||||
option (google.api.http) = {
|
||||
put: "/idps/oauth/{id}"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "org.idp.write"
|
||||
};
|
||||
}
|
||||
|
||||
// Add a new Google identity provider in the organisation
|
||||
rpc AddGoogleProvider(AddGoogleProviderRequest) returns (AddGoogleProviderResponse) {
|
||||
@ -7874,6 +7897,39 @@ message GetProviderByIDResponse {
|
||||
zitadel.idp.v1.Provider idp = 1;
|
||||
}
|
||||
|
||||
message AddGenericOAuthProviderRequest {
|
||||
string name = 1 [(validate.rules).string = {min_len: 1, 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}];
|
||||
string authorization_endpoint = 4 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string token_endpoint = 5 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string user_endpoint = 6 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
repeated string scopes = 7 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||
zitadel.idp.v1.Options provider_options = 8;
|
||||
}
|
||||
|
||||
message AddGenericOAuthProviderResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message UpdateGenericOAuthProviderRequest {
|
||||
string id = 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}];
|
||||
// client_secret will only be updated if provided
|
||||
string client_secret = 4 [(validate.rules).string = {max_len: 200}];
|
||||
string authorization_endpoint = 5 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string token_endpoint = 6 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
string user_endpoint = 7 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||
repeated string scopes = 8 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||
zitadel.idp.v1.Options provider_options = 9;
|
||||
}
|
||||
|
||||
message UpdateGenericOAuthProviderResponse {
|
||||
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}];
|
||||
|
Loading…
x
Reference in New Issue
Block a user